Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve performance of fmt::format on integer formatting #193

Closed
vitaut opened this issue Aug 5, 2015 · 8 comments
Closed

Improve performance of fmt::format on integer formatting #193

vitaut opened this issue Aug 5, 2015 · 8 comments

Comments

@vitaut
Copy link
Contributor

vitaut commented Aug 5, 2015

Current results:

['Method'                      , 'Time, s' , 'Time ratio' ],
['fmt::FormatInt'              ,   0.130366,           1.0],
['fmt::Writer'                 ,    0.15293, 1.17308193854],
['cppx::decimal_from'          ,   0.158245, 1.21385177117],
['karma::generate'             ,   0.163913, 1.25732936502],
['karma::generate+std::string' ,   0.317622, 2.43638678797],
['fmt::Writer+std::string'     ,   0.327253, 2.51026341224],
['ltoa'                        ,   0.489808, 3.75717595078],
['itostr'                      ,   0.615213,  4.7191215501],
['sprintf'                     ,   0.883171, 6.77455011276],
['fmt::format'                 ,   0.956393, 7.33621496402], <---
['boost::lexical_cast'         ,   0.994558, 7.62896767562],
['sprintf+std::string'         ,    1.02793, 7.88495466609],
['std::to_string'              ,    1.34569, 10.3224000123],
['std::stringstream'           ,    1.38597, 10.6313762791],
['boost::format'               ,    4.07773, 31.2790911741]

For comparison, here are results from 1b80148:

['Method'                      , 'Time, s' , 'Time ratio' ],
['fmt::FormatInt'              ,   0.141162,           1.0],
['karma::generate'             ,   0.162126,  1.1485102223],
['cppx::decimal_from'          ,   0.167754, 1.18837930888],
['fmt::Writer'                 ,   0.192687, 1.36500616313],
['karma::generate+std::string' ,   0.321725, 2.27911902637],
['fmt::Writer+std::string'     ,   0.387114, 2.74233858971],
['fmt::format'                 ,   0.462457,  3.2760728808], <---
['ltoa'                        ,   0.487219, 3.45148836089],
['itostr'                      ,   0.665112, 4.71169294853],
['sprintf'                     ,   0.894235, 6.33481390176],
['boost::lexical_cast'         ,    1.04254, 7.38541533841],
['sprintf+std::string'         ,    1.04865, 7.42869894164],
['std::stringstream'           ,    1.27094, 9.00341451665],
['std::to_string'              ,    1.34653, 9.53889857044],
['boost::format'               ,    4.40832, 31.2288009521]
@patlecat
Copy link

Cool now you beat even Karma and C, impressive 👯

@vitaut
Copy link
Contributor Author

vitaut commented Aug 12, 2015

Thanks! It's been for a while already, but some regression crept in.

@vitaut
Copy link
Contributor Author

vitaut commented Sep 15, 2015

Change in performance is caused by making fmt::format return std::string in a126492. Constructing string objects takes about the same time as formatting.

@vitaut
Copy link
Contributor Author

vitaut commented Sep 15, 2015

The problem with the int_generator benchmark is that some tests construct temporary strings (std::to_string, std::stringstream, fmt::format) and some don't (sprintf+std::string, karma::generate+std::string) which makes comparison meaningless. Need to fix this.

@vitaut
Copy link
Contributor Author

vitaut commented Sep 15, 2015

Fixed the benchmark in fmtlib/format-benchmark@bd23f14. Updated results:

['Method'                      , 'Time, s' , 'Time ratio' ],
['fmt::FormatInt'              ,   0.147907,           1.0],
['karma::generate'             ,   0.167082, 1.12964227521],
['fmt::Writer'                 ,   0.168074,  1.1363491924],
['cppx::decimal_from'          ,   0.170386, 1.15198063648],
['ltoa'                        ,   0.487298, 3.29462432474],
['itostr'                      ,   0.664632, 4.49358042554],
['fmt::Writer+std::string'     ,   0.694602, 4.69620775217],
['karma::generate+std::string' ,   0.735435, 4.97227987857],
['sprintf'                     ,   0.884361,  5.9791693429],
['boost::lexical_cast'         ,   0.967354, 6.54028544964],
['fmt::format'                 ,    1.09314, 7.39072525303],
['std::stringstream'           ,    1.21641, 8.22415436727],
['std::to_string'              ,    1.31157,  8.8675316246],
['sprintf+std::string'         ,     1.3987, 9.45661800997],
['boost::format'               ,    4.19163, 28.3396323365]

fmt::format's performance can be improved a bit bringing it back to sprintf level. However, std::string construction is a limiting factor as can be seen from the results above - it adds about half a second to the run time for each method. So for better performance one should avoid std::string-based methods and use fmt::Writer or fmt::FormatInt.

@vitaut
Copy link
Contributor Author

vitaut commented Sep 16, 2015

Corrected results after fixing an std::string copying issue in fmtlib/format-benchmark@fc4cd13:

['Method'                      , 'Time, s' , 'Time ratio' ],
['fmt::FormatInt'              ,   0.131329,           1.0],
['fmt::Writer'                 ,   0.151219, 1.15145169764],
['karma::generate'             ,   0.161277, 1.22803798095],
['cppx::decimal_from'          ,    0.16367, 1.24625939435],
['ltoa'                        ,   0.488084, 3.71649826009],
['itostr'                      ,   0.575497,  4.3821014399],
['karma::generate+std::string' ,   0.649735, 4.94738405074],
['fmt::Writer+std::string'     ,   0.665199, 5.06513412879],
['sprintf'                     ,   0.883342, 6.72617624439],
['boost::lexical_cast'         ,   0.891263,  6.7864904172],
['fmt::format'                 ,   0.988134, 7.52411120164],
['std::stringstream'           ,    1.22015, 9.29078878237],
['std::to_string'              ,    1.28301, 9.76943401686],
['sprintf+std::string'         ,    1.35638, 10.3281072726],
['boost::format'               ,    4.12666, 31.4223058121]

@vitaut
Copy link
Contributor Author

vitaut commented Oct 23, 2015

One possibility to improve fmt::format performance is to format directly to std::string which is now possible because buffer management is decoupled from writers.

@vitaut
Copy link
Contributor Author

vitaut commented Jul 22, 2017

The current numbers (on std) look pretty good:

['Method'                      , 'Time, s' , 'Time ratio' ],
['fmt::FormatInt'              ,   0.133837,           1.0],
['cppx::decimal_from'          ,   0.150949, 1.12785702011],
['fmt::basic_writer'           ,   0.151999, 1.13570238424],
['karma::generate'             ,   0.167353, 1.25042402325],
['itostr'                      ,   0.242164, 1.80939501035],
['fmt::basic_writer+std::string',   0.280116, 2.09296382914],
['karma::generate+std::string' ,   0.304879, 2.27798740259],
['boost::lexical_cast'         ,   0.454893, 3.39885831272],
['ltoa'                        ,   0.490139, 3.66220850736],
['fmt::format'                 ,    0.55959, 4.18113077848],
['sprintf'                     ,   0.943337, 7.04840216084],
['sprintf+std::string'         ,    1.07682, 8.04575715236],
['std::to_string'              ,    1.26133, 9.42437442561],
['std::stringstream'           ,     2.2325, 16.6807385103],
['boost::format'               ,    4.28298,  32.001464468],

Formatting directly to std::string may actually result in more re-allocations so probably not worth it.

@vitaut vitaut closed this as completed Jul 22, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants