////
Copyright 2023 Matt Borland
Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
////

= Benchmarks
:idprefix: benchmarks

This section describes a range of performance benchmarks that have been run comparing this library with the standard library, and how to run your own benchmarks if required.

The values are relative to the performance of `std::printf` and `std::strtoX`.
Larger numbers are more performant (e.g. 2.00 means twice as fast, and 0.50 means it takes twice as long).
`std::printf` and `std::strtoX` are always listed first as they will be the reference value.

== How to run the Benchmarks
[#run_benchmarks_]

To run the benchmarks yourself, navigate to the test folder and define `BOOST_CHARCONV_RUN_BENCHMARKS` when running the tests.
An example on Linux with b2: `../../../b2 cxxstd=20 toolset=gcc-13 define=BOOST_CHARCONV_RUN_BENCHMARKS STL_benchmark linkflags="-lfmt" -a release` .

Additionally, you will need the following:

* A compiler with full `<charconv>` support:
** GCC 11 or newer
** MSVC 19.24 or newer
* https://github.com/google/double-conversion[libdouble-conversion]
* https://github.com/fmtlib/fmt[{fmt}]

== Results
[#benchmark_results_]

=== x86_64 Linux

Data in tables 1 - 4 were run on Ubuntu 23.04 with x86_64 architecture using GCC 13.1.0 with libstdc++.

==== Floating Point

.to_chars floating point with the shortest representation
|===
|Function|Relative Performance (float / double)

|std::printf
|1.00 / 1.00
|Boost.lexical_cast
|0.56 / 0.49
|Boost.spirit.karma
|1.70 / 2.62
|std::to_chars
|4.01 / 6.03
|Boost.Charconv.to_chars
|4.46 / 6.20
|Google double-conversion
|1.26 / 1.91
|{fmt}
|2.52 / 3.63
|===

.from_chars floating point with scientific formatting
|===
|Function|Relative Performance (float / double)

|std::strto(f/d)
|1.00 / 1.00
|Boost.lexical_cast
|0.33 / 0.42
|Boost.spirit.qi
|3.17 / 4.65
|std::from_chars
|3.23 / 5.77
|Boost.Charconv.from_chars
|3.28 / 5.75
|Google double-conversion
|1.16 / 1.30
|===

==== Integral

.to_chars base 10 integers
|===
|Function|Relative Performance (uint32_t / uint64_t)

|std::printf
|1.00 / 1.00
|Boost.lexical_cast
|1.80 / 1.38
|Boost.spirit.karma
|2.81 / 1.62
|std::to_chars
|4.06 / 2.45
|Boost.Charconv.to_chars
|4.13 / 2.48
|{fmt}
|2.88 / 2.21
|===

.from_chars base 10 integers
|===
|Function|Relative Performance (uint32_t / uint64_t)

|std::strto(ul,ull)
|1.00 / 1.00
|Boost.lexical_cast
|0.53 / 0.52
|Boost.spirit.qi
|2.24 / 1.49
|std::from_chars
|1.97 / 1.68
|Boost.Charconv.from_chars
|2.54 / 1.78
|===

=== x86_64 Windows

Data in tables 5 - 8 were run on Windows 11 with x86_64 architecture using MSVC 14.3 (V17.7.0).

==== Floating Point

.to_chars floating point with the shortest representation
|===
|Function|Relative Performance (float / double)

|std::printf
|1.00 / 1.00
|Boost.lexical_cast
|0.50 / 0.70
|Boost.spirit.karma
|2.23 / 7.58
|std::to_chars
|5.58 / 15.77
|Boost.Charconv.to_chars
|5.62 / 15.26
|===

.from_chars floating point with scientific formatting
|===
|Function|Relative Performance (float / double)

|std::strto(f/d)
|1.00 / 1.00
|Boost.lexical_cast
|0.14 / 0.20
|Boost.spirit.qi
|2.03 / 4.58
|std::from_chars
|1.01 / 1.23
|Boost.Charconv.from_chars
|2.06 / 5.21
|===

==== Integral

.to_chars base 10 integers
|===
|Function|Relative Performance (uint32_t / uint64_t)

|std::printf
|1.00 / 1.00
|Boost.lexical_cast
|0.68 / 0.68
|Boost.spirit.karma
|2.75 / 1.67
|std::to_chars
|2.75 / 2.10
|Boost.Charconv.to_chars
|2.75 / 2.06
|===

.from_chars base 10 integers
|===
|Function|Relative Performance (uint32_t / uint64_t)

|std::strto(ul,ull)
|1.00 / 1.00
|Boost.lexical_cast
|0.46 / 0.39
|Boost.spirit.qi
|1.94 / 1.63
|std::from_chars
|2.43 / 2.18
|Boost.Charconv.from_chars
|2.68 / 2.27
|===

=== ARM MacOS

Data in tables 9-12 were run on MacOS Ventura 13.5.2 with M1 Pro architecture using Homebrew GCC 13.2.0 with libstdc++.

==== Floating Point

.to_chars floating point with the shortest representation
|===
|Function|Relative Performance (float / double)

|std::printf
|1.00 / 1.00
|Boost.lexical_cast
|0.58 / 0.16
|Boost.spirit.karma
|1.39 / 1.22
|std::to_chars
|6.78 / 6.47
|Boost.Charconv.to_chars
|7.25 / 6.86
|Google double-conversion
|2.26 / 2.16
|{fmt}
|3.78 / 3.38
|===

.from_chars floating point with scientific formatting
|===
|Function|Relative Performance (float / double)

|std::strto(f/d)
|1.00 / 1.00
|Boost.lexical_cast
|0.06 / 0.06
|Boost.spirit.qi
|1.12 / 1.06
|std::from_chars
|1.32 / 1.65
|Boost.Charconv.from_chars
|1.28 / 1.63
|Google double-conversion
|0.45 / 0.32

|===

==== Integral

.to_chars base 10 integers
|===
|Function|Relative Performance (uint32_t / uint64_t)

|std::printf
|1.00 / 1.00
|Boost.lexical_cast
|2.08 / 1.75
|Boost.spirit.karma
|4.17 / 2.06
|std::to_chars
|6.25 / 4.12
|Boost.Charconv.to_chars
|6.25 / 4.12
|{fmt}
|5.29 / 3.47
|===

.from_chars base 10 integers
|===
|Function|Relative Performance (uint32_t / uint64_t)

|std::strto(ul,ull)
|1.00 / 1.00
|Boost.lexical_cast
|0.56 / 0.54
|Boost.spirit.qi
|1.39 / 1.33
|std::from_chars
|1.92 / 1.65
|Boost.Charconv.from_chars
|2.27 / 1.65
|===
