为什么 libfmt 比 stringstream append 慢?

1 stringstream fmt

我有一个代码库,它使用业务逻辑将 csv 文件转换为类似 xml 的配置文件。此代码大量使用字符串流来构造配置文件,其中一些文件中包含内联 SQL 语句。我正在考虑重构部分代码,并决定使用 libfmt 来构造配置字符串。与字符串流相比,代码肯定更具可读性,但我也希望性能有显着提升。

然而,我正在针对其他构造字符串的方法测试 libfmt 的简单基准,我发现即使与字符串流相比,它仍然很慢。(虽然上面的测试还包括 std::format (主要是出于好奇),但我们还没有迁移到 C++20,因此无法使用它。)

为什么会出现这种情况?我可以采取什么措施来改善它?

我已经查看了以下相关问题,但我的用例有所不同。为什么 {fmt} 比 std::stringstream 慢?

我尝试过的基准代码可以在这里找到:https ://godbolt.org/z/xrhPdarqa

vit*_*aut 7

由于多种原因,godbolt 不适合这样的基准测试,包括它使用 {fmt} 和其他库的调试版本。因此,您可以有效地将 {fmt} 的调试版本与 sstream 的优化版本进行比较。您甚至会收到来自 Google Benchmark 本身的警告:

***WARNING*** Library was built as DEBUG. Timings may be affected.
Run Code Online (Sandbox Code Playgroud)

部分解决方法是使用仅标头模式,该模式显示在这种情况下 {fmt} 比 sstream 快 2.5-3 倍(https://godbolt.org/z/WY4d3h9vr):

--------------------------------------------------------------------
Benchmark                          Time             CPU   Iterations
--------------------------------------------------------------------
BM_test_string_append            146 ns         82.2 ns      7974239
BM_test_sstream_append           674 ns          344 ns      1465041
BM_test_fmt_string_append        273 ns          125 ns      6728817
BM_test_std_format_append        415 ns          223 ns      2596699
Run Code Online (Sandbox Code Playgroud)