The excellent {fmt} largely served as the blueprint for the C++20 standard formatting library. That alone speaks for its quality. But I was curious: should you now just use std::format for everything, or is fmt::format still a good option? In this particular instance, I wanted to know which one is faster, so I wrote a small benchmark. Of course, the outcome very much depends on the standard library you are using. In my case, I’m using Visual Studio 17.13.0 and its standard library, and {fmt} version 11.1.3.
I started with a benchmark helper function:
template <std::invocable<> F> steady_clock::duration benchmark(std::string_view label, F f)
{
auto start = steady_clock::now();
f();
auto end = steady_clock::now();
auto time = end - start;
auto us = duration_cast<nanoseconds>(time).count() / 1000.0;
std::cout << std::format("{0} took {1:.3f}us", label, us) << std::endl;
return time;
}
Then I called it with a lambda like this, with NUMBER_OF_ITERATIONS set to 500000:
int integer = 567800;
float real = 1234.0089f;
for (std::size_t i = 0; i < NUMBER_OF_ITERATIONS; ++i)
auto _ = fmt::format("an int: {}, and a float: {}", integer, real);
… and the same thing with std::format.
Interestingly, fmt::format only needed about 75%-80% of time of std::format in a release build, while the situation reversed for a debug build to about 106%-108%.
It seems hard to construct a benchmark with low overhead of other things, while still avoiding that the compiler can optimize everything away. My code assumes the compiler keeps the formatting even after throwing it away. So take all my results with a grain of salt!
