From c0dfdd4ef5b35b4da5852d7febd04cd03c9e7fc1 Mon Sep 17 00:00:00 2001 From: Aleksandr Orefkov Date: Tue, 3 Feb 2026 23:28:15 +0300 Subject: [PATCH] Update results --- bench/process_result.cpp | 41 ++-- bench/results.css | 13 ++ bench/results.html | 438 +++++++++++++++++++-------------------- 3 files changed, 256 insertions(+), 236 deletions(-) diff --git a/bench/process_result.cpp b/bench/process_result.cpp index 9ca58b6..52c79a1 100644 --- a/bench/process_result.cpp +++ b/bench/process_result.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace simstr; @@ -193,41 +194,46 @@ void write_one_result(out_t& out, ssa result, ssa line, auto& script_text, bool script_text += e_choice(result[0] == 'N', "NaN", result) + e_choice(last, "]", ","); } -ssa extract_source_for_benchmark(ssa benchName, ssa sourceText) { - if (benchName == "ReplaceStr") { - int t = 0; - } - static hashStrMapA textes; +std::pair extract_source_for_benchmark(ssa benchName, ssa sourceText) { + static hashStrMapA> textes; + static auto lines_pos = [&]() { + std::map l = {{0, 0}}; + size_t line = 0; + sourceText.for_all_finded([&](size_t pos){ + l.emplace(pos, ++line); + }, "\n"); + return l; + }(); size_t delim = benchName.find_last('/'); if (delim != str::npos && benchName(delim + 1).to_int().ec == IntConvertResult::Success) { benchName.len = delim; } - auto [it, not_exist] = textes.try_emplace(benchName); + auto [it, not_exist] = textes.try_emplace(benchName, stringa{}, 0); if (not_exist) { // Ищем имя функции для этого бенчмарка // Looking for the name of the function for this benchmark size_t start = sourceText.find(lstringa<128>{"->Name(\"" + e_repl(benchName, "\"", "\\\"") + "\")"}); if (start == str::npos) { std::cerr << "Can not found benchmark function name for " << benchName << std::endl; - return stra::empty_str; + return {stra::empty_str, 0}; } start = sourceText(0, start).find('(', sourceText.find_last('\n', start - 1)); if (start == str::npos) { std::cerr << "Can not found benchmark function name for " << benchName << std::endl; - return stra::empty_str; + return {stra::empty_str, 0}; } start++; size_t end = sourceText.find_first_of(")<,", start); ssa funcName = sourceText.from_to(start, end); - auto [func_it, not_exist] = textes.try_emplace(funcName); + auto [func_it, not_exist] = textes.try_emplace(funcName, stringa{}, 0); if (not_exist) { // Теперь ищем саму эту функцию // Now we look for this function itself start = sourceText.find(lstringa<128>{funcName + "(benchmark::State"}); if (start == str::npos) { std::cerr << "Can not found source function " << funcName << " for benchmark " << benchName << std::endl; - return stra::empty_str; + return {stra::empty_str, 0}; } start = sourceText.find_last('\n', start); size_t templ_start = sourceText.find_last('\n', start) + 1; @@ -255,15 +261,16 @@ ssa extract_source_for_benchmark(ssa benchName, ssa sourceText) { throw std::runtime_error{"Not found end of func"}; } lstringa<2048> text{sourceText.from_to(beginLine, end + indent.length() + 1), indent, "\n"}; - func_it->second = repl_html_symbols(text(1)); + func_it->second.first = repl_html_symbols(text(1)); } else { end = sourceText.find("\n}\n", start); - func_it->second = repl_html_symbols(sourceText.from_to(start, end + 2)); + func_it->second.first = repl_html_symbols(sourceText.from_to(start, end + 2)); } + func_it->second.second = lines_pos.lower_bound(start)->second; } it->second = func_it->second; } - return it->second; + return {it->second.first, it->second.second}; } void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText, ssa commentsText) { @@ -280,13 +287,13 @@ void write_benchmarks(out_t& out, const results_vector& results, ssa sourceText, ssa line = splitters[0].next(), benchName, result; if (auto rm = line.find("_mean"); rm != str::npos) { benchName = extract_name_result(line, result)(0, rm); - auto source = extract_source_for_benchmark(benchName, sourceText); + auto [source, line_num] = extract_source_for_benchmark(benchName, sourceText); auto comment = extract_comment(commentsText, benchName); // Нужно вывести название бенча и коммент // Need to display title and comment - out += "\n" + - repl_html_symbols(benchName) + - "" + + out += "\n" + repl_html_symbols(benchName) + + "" + source + "" + e_if(!comment.is_empty(), " >> " + comment + "") + ""; diff --git a/bench/results.css b/bench/results.css index fafcb72..e70d632 100644 --- a/bench/results.css +++ b/bench/results.css @@ -19,6 +19,19 @@ table th { text-align: center; } +.tooltip a:any-link { + text-decoration: none; +} +.tooltip a:link { + color: black; +} +.tooltip a:visited { + color: black; +} +.tooltip a:hover { + text-decoration: underline; +} + table tr:hover td { background-color: lightcyan; } diff --git a/bench/results.html b/bench/results.html index f8702b9..431390c 100644 --- a/bench/results.html +++ b/bench/results.html @@ -301,7 +301,7 @@ Load Average: 0.24, 0.68, 0.48

# Concatenate string + Number + "Literal"

- - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Concat std::string and number by std to std::stringvoid ConcatStdToStd(benchmark::State& state) { +
Concat std::string and number by std to std::stringvoid ConcatStdToStd(benchmark::State& state) { std::string s1 = "start "; for (auto _: state) { for (int i = 1; i <= 100'000; i *= 10) { @@ -311,7 +311,7 @@ Load Average: 0.24, 0.68, 0.48 } } }2342112663151022
Concat std::string and number by StrExpr to std::stringvoid ConcatSimToStd(benchmark::State& state) { +
Concat std::string and number by StrExpr to std::stringvoid ConcatSimToStd(benchmark::State& state) { std::string s1 = "start "; for (auto _: state) { for (int i = 1; i <= 100'000; i *= 10) { @@ -321,7 +321,7 @@ Load Average: 0.24, 0.68, 0.48 } } }104111159213449
Concat stringa and number by StrExpr to simstr::stringavoid ConcatSimToSim(benchmark::State& state) { +
Concat stringa and number by StrExpr to simstr::stringavoid ConcatSimToSim(benchmark::State& state) { stra s1 = "start "; for (auto _: state) { for (int i = 1; i <= 100'000; i *= 10) { @@ -338,7 +338,7 @@ Unlike std::string, stringa holds 23 characters in SSO instead of 15, so at the end of the std::string test, memory has to be allocated, while in stringa , the entire test is included in SSO.62.472.667.5121230
Concat stringa and number by e_concat to simstr::stringavoid ConcatSimToSimConcat(benchmark::State& state) { +
Concat stringa and number by e_concat to simstr::stringavoid ConcatSimToSimConcat(benchmark::State& state) { stra s1 = "start "; for (auto _: state) { for (int i = 1; i <= 100'000; i *= 10) { @@ -357,7 +357,7 @@ while in stringa , the entire test is included in SSO.

# Concatenate string + Hex Number + "Literal"

- - - - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Concat std::string and format hex number and literal to std::stringvoid ConcatStdToFmtHex(benchmark::State& state) { +
Concat std::string and format hex number and literal to std::stringvoid ConcatStdToFmtHex(benchmark::State& state) { // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. std::string s1 = "art "; for (auto _: state) { @@ -369,7 +369,7 @@ while in stringa , the entire test is included in SSO.68465373110331423
std::format std::string and hex number by literal to std::stringvoid ConcatAllFmtToHex(benchmark::State& state) { +
std::format std::string and hex number by literal to std::stringvoid ConcatAllFmtToHex(benchmark::State& state) { // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. std::string s1 = "art "; for (auto _: state) { @@ -381,7 +381,7 @@ while in stringa , the entire test is included in SSO.872960152418411601
Concat std::string and std::to_chars and string to std::stringvoid ConcatStdToCharsHex(benchmark::State& state) { +
Concat std::string and std::to_chars and string to std::stringvoid ConcatStdToCharsHex(benchmark::State& state) { // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. std::string s1 = "art "; for (auto _: state) { @@ -395,7 +395,7 @@ while in stringa , the entire test is included in SSO.203197191251640
Concat std::string and hex number and literal by StrExpr to std::stringvoid ConcatSimToStdHex(benchmark::State& state) { +
Concat std::string and hex number and literal by StrExpr to std::stringvoid ConcatSimToStdHex(benchmark::State& state) { // We use a short string so that the longest result is 15 characters and fits in the std::string SSO buffer. std::string s1 = "art "; for (auto _: state) { @@ -407,7 +407,7 @@ while in stringa , the entire test is included in SSO.14212780.0119422
Concat stringa and hex number and literal by StrExpr to simstr::stringavoid ConcatSimToSimHex(benchmark::State& state) { +
Concat stringa and hex number and literal by StrExpr to simstr::stringavoid ConcatSimToSimHex(benchmark::State& state) { // stringa SSO buffer is 23, but we use a short string to compare under the same conditions stra s1 = "art "; for (auto _: state) { @@ -419,7 +419,7 @@ while in stringa , the entire test is included in SSO.12412475.099.3212
Concat stringa and hex number and literal by e_concat to simstr::stringavoid ConcatSimToSimHexC(benchmark::State& state) { +
Concat stringa and hex number and literal by e_concat to simstr::stringavoid ConcatSimToSimHexC(benchmark::State& state) { // stringa SSO buffer is 23, but we use a short string to compare under the same conditions stra s1 = "art "; for (auto _: state) { @@ -431,7 +431,7 @@ while in stringa , the entire test is included in SSO.12613480.4104213
Subst stringa and hex number by e_subst literal to simstr::stringavoid ConcatSimToSimHexS(benchmark::State& state) { +
Subst stringa and hex number by e_subst literal to simstr::stringavoid ConcatSimToSimHexS(benchmark::State& state) { // stringa SSO buffer is 23, but we use a short string to compare under the same conditions stra s1 = "art "; for (auto _: state) { @@ -442,7 +442,7 @@ while in stringa , the entire test is included in SSO.216173148175486
Subst stringa and hex number by e_vsubst stra to simstr::stringavoid ConcatSimToSimHexVS(benchmark::State& state) { +
Subst stringa and hex number by e_vsubst stra to simstr::stringavoid ConcatSimToSimHexVS(benchmark::State& state) { // stringa SSO buffer is 23, but we use a short string to compare under the same conditions stra s1 = "art "; for (auto _: state) { @@ -466,7 +466,7 @@ while in stringa , the entire test is included in SSO.

# format/vformat and subst/vsubst octal number

- - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
e_subst("art {} end", e_int<8, f::w<10> | f::p | f::z>(i))void SubstSimToSimBin(benchmark::State& state) { +
e_subst("art {} end", e_int<8, f::w<10> | f::p | f::z>(i))void SubstSimToSimBin(benchmark::State& state) { static bool first = true; for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { @@ -475,7 +475,7 @@ while in stringa , the entire test is included in SSO.168145162206641
std::format("art {:#010o} end", i)void FormatStdToStdBin(benchmark::State& state) { +
std::format("art {:#010o} end", i)void FormatStdToStdBin(benchmark::State& state) { for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { std::string str = std::format("art {:#010o} end", i); @@ -483,7 +483,7 @@ while in stringa , the entire test is included in SSO.10041261136916781750
e_vsubst(pattern, e_int<8, f::w<10> | f::p | f::z>(i))void VSubstSimToSimBin(benchmark::State& state) { +
e_vsubst(pattern, e_int<8, f::w<10> | f::p | f::z>(i))void VSubstSimToSimBin(benchmark::State& state) { ssa pattern = "art {} end"; for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { @@ -492,7 +492,7 @@ while in stringa , the entire test is included in SSO.3633413053541016
std::vformat(pattern, std::make_format_args(i))void VFormatStdToStdBin(benchmark::State& state) { +
std::vformat(pattern, std::make_format_args(i))void VFormatStdToStdBin(benchmark::State& state) { std::string_view pattern = "art {:#010o} end"; static bool first = true; for (auto _: state) { @@ -511,7 +511,7 @@ while in stringa , the entire test is included in SSO.

# Concatenate string + "Literal"

- - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Concat std::string by std to std::stringvoid ConcatStdToStdS(benchmark::State& state) { +
Concat std::string by std to std::stringvoid ConcatStdToStdS(benchmark::State& state) { std::string s1 = "start "; for (auto _: state) { for (int i = 1; i <= 100'000; i *= 10) { @@ -521,7 +521,7 @@ while in stringa , the entire test is included in SSO.55.852.040.955.096.4
Concat std::string by StrExpr to std::stringvoid ConcatSimToStdS(benchmark::State& state) { +
Concat std::string by StrExpr to std::stringvoid ConcatSimToStdS(benchmark::State& state) { std::string s1 = "start "; for (auto _: state) { for (int i = 1; i <= 100'000; i *= 10) { @@ -531,7 +531,7 @@ while in stringa , the entire test is included in SSO.39.535.840.775.6111
Concat stringa by StrExpr to stringavoid ConcatSimToSimS(benchmark::State& state) { +
Concat stringa by StrExpr to stringavoid ConcatSimToSimS(benchmark::State& state) { stra s1 = "start "; for (auto _: state) { for (int i = 1; i <= 100'000; i *= 10) { @@ -549,14 +549,14 @@ while in stringa , the entire test is included in SSO.

# Find three concatenated string in string_view

- - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Find concat three std::stringsize_t find_pos_str(std::string_view src, std::string_view name) { +
Find concat three std::stringsize_t find_pos_str(std::string_view src, std::string_view name) { // before C++26 we can not concatenate string and string_view... return src.find("\n- "s + std::string{name} + " -\n"); }113129204230149
Find concat three strexprsize_t find_pos_exp(ssa src, ssa name) { +
Find concat three strexprsize_t find_pos_exp(ssa src, ssa name) { return src.find(std::string{"\n- " + name + " -\n"}); }48.054.9113129106
Find concat three simstrsize_t find_pos_sim(ssa src, ssa name) { +
Find concat three simstrsize_t find_pos_sim(ssa src, ssa name) { return src.find(lstringa<200>{"\n- " + name + " -\n"}); } >> Если результат конкатенации меньше 207 символов, он собирается в буфере на стеке, без аллокации и деалокации. @@ -570,7 +570,7 @@ it is collected in a stack-based buffer, without allocation or deallocation.

# Build Type Name

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
BuildTypeNameStr 0/0std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { +
BuildTypeNameStr 0/0std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { std::string res{type_name}; if (prec) { res += "(" + std::to_string(prec); @@ -581,19 +581,19 @@ it is collected in a stack-based buffer, without allocation or deallocation.7.5110.28.1617.618.0
BuildTypeNameExp 0/0std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { +
BuildTypeNameExp 0/0std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { if (prec) { return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; } return type_name; }6.396.447.6614.017.5
BuildTypeNameSim 0/0stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { +
BuildTypeNameSim 0/0stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { if (prec) { return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; } return type_name; }4.205.147.7314.815.6
BuildTypeNameStr 10/10std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { +
BuildTypeNameStr 10/10std::string buildTypeNameStr(std::string_view type_name, size_t prec, size_t scale) { std::string res{type_name}; if (prec) { res += "(" + std::to_string(prec); @@ -604,13 +604,13 @@ it is collected in a stack-based buffer, without allocation or deallocation.65.685.159.779.7296
BuildTypeNameExp 10/10std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { +
BuildTypeNameExp 10/10std::string buildTypeNameExp(ssa type_name, size_t prec, size_t scale) { if (prec) { return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; } return type_name; }33.726.532.437.9106
BuildTypeNameSim 10/10stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { +
BuildTypeNameSim 10/10stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { if (prec) { return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; } @@ -627,7 +627,7 @@ it is collected in a stack-based buffer, without allocation or deallocation.

# Replace string by copy

- -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Concat with replace strstd::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) { +
Concat with replace strstd::string make_str_str(std::string_view from, std::string_view pattern, std::string_view repl) { auto str_replace = [](std::string_view from, std::string_view pattern, std::string_view repl) { std::string result; for (size_t offset = 0; ;) { @@ -644,7 +644,7 @@ it is collected in a stack-based buffer, without allocation or deallocation."; }210228349341496
Concat with replace expstd::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) { +
Concat with replace expstd::string make_str_exp(std::string_view from, std::string_view pattern, std::string_view repl) { return "<" + e_repl(from, pattern, repl) + ">"; } >> В simstr строковое выражение для замены подстрок есть "из коробки". @@ -656,7 +656,7 @@ simstr has a string expression for replacing substrings out of the box.

# Create Empty Str

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string e;template<typename T> +
std::string e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; @@ -664,35 +664,35 @@ void CreateEmpty(benchmark::State& state) { } } >> Пустые строки, ничего необычного. Empty lines, nothing unusual.1.091.111.132.222.16
std::string_view e;template<typename T> +
std::string_view e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }0.3650.7330.3641.880.989
ssa e;template<typename T> +
ssa e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }0.3630.1820.3571.470.945
stringa e;template<typename T> +
stringa e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }0.7300.7380.7422.202.16
lstringa<20> e;template<typename T> +
lstringa<20> e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }1.131.121.112.552.22
lstringa<40> e;template<typename T> +
lstringa<40> e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; @@ -710,7 +710,7 @@ void CreateEmpty(benchmark::State& state) {

# Create Str from short literal (9 symbols)

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string e = "Test text";template<typename T> +
std::string e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; @@ -720,7 +720,7 @@ void CreateShortLiteral(benchmark::State& state) { время тратится только на копирование 10 байтов. The short literal is placed in the internal std::string buffer; time is spent only copying 10 bytes.1.831.991.802.602.29
std::string_view e = "Test text";template<typename T> +
std::string_view e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; @@ -730,14 +730,14 @@ void CreateShortLiteral(benchmark::State& state) { указатель на текст и его длина. Both string_view and ssa are essentially the same thing: a pointer to text and its length.0.7340.7780.7301.791.24
ssa e = "Test text";template<typename T> +
ssa e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } }0.3720.7470.3681.790.976
stringa e = "Test text";template<typename T> +
stringa e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; @@ -747,7 +747,7 @@ void CreateShortLiteral(benchmark::State& state) { сохраняет только указатель на текст и его длину. When initialized with a constant literal, stringa also stores only a pointer to the text and its length.1.111.091.112.212.22
lstringa<20> e = "Test text";template<typename T> +
lstringa<20> e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; @@ -757,7 +757,7 @@ void CreateShortLiteral(benchmark::State& state) { время уходит только на копирование байтов. The internal buffer is sufficient to accommodate characters; time is spent only on copying bytes.1.851.831.842.622.64
lstringa<40> e = "Test text";template<typename T> +
lstringa<40> e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; @@ -775,7 +775,7 @@ void CreateShortLiteral(benchmark::State& state) {

# Create Str from long literal (30 symbols)

- - - - - -

# Create copy of Str with 9 symbols

Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string e = "123456789012345678901234567890";template<typename T> +
std::string e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; @@ -787,7 +787,7 @@ void CreateLongLiteral(benchmark::State& state) { Here, the literal doesn't fit into the internal buffer, and 30 bytes are allocated and copied. But how much slower is allocation under Windows than under Linux, 20 ns vs. 70 ns...19.319.070.180.216.3
std::string_view e = "123456789012345678901234567890";template<typename T> +
std::string_view e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; @@ -797,14 +797,14 @@ void CreateLongLiteral(benchmark::State& state) { запоминания указателя на текст и его размера. string_view and ssa still do nothing except remember the pointer to the text and its size.0.7390.7350.7571.821.23
ssa e = "123456789012345678901234567890";template<typename T> +
ssa e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } }0.3860.7220.3911.840.976
stringa e = "123456789012345678901234567890";template<typename T> +
stringa e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; @@ -812,7 +812,7 @@ void CreateLongLiteral(benchmark::State& state) { } } >> stringa на константных литералах не отстает! stringa doesn't lag behind on constant literals!1.121.091.122.522.27
lstringa<20> e = "123456789012345678901234567890";template<typename T> +
lstringa<20> e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; @@ -821,7 +821,7 @@ void CreateLongLiteral(benchmark::State& state) { } >> lstringa<20> может вместить в себя до 23 символов, Очевидно, что для 30-и символов уже нужна аллокация. Obviously, 30 characters already require allocation.21.720.376.977.317.1
lstringa<40> e = "123456789012345678901234567890";template<typename T> +
lstringa<40> e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; @@ -842,7 +842,7 @@ bytes are simply copied.2.60
- - - - - -

# Create copy of Str with 30 symbols

Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string e = "Test text"; auto c{e};template<typename T> +
std::string e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { @@ -852,7 +852,7 @@ void CopyShortString(benchmark::State& state) { } } >> Строка в пределах SSO, так что просто копирует байты. The string is within the SSO, so it just copies the bytes.6.074.881.825.242.21
std::string_view e = "Test text"; auto c{e};template<typename T> +
std::string_view e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { @@ -861,7 +861,7 @@ void CopyShortString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }0.3820.3780.3692.911.24
ssa e = "Test text"; auto c{e};template<typename T> +
ssa e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { @@ -873,7 +873,7 @@ void CopyShortString(benchmark::State& state) { только информация о строке. ssa and string_view don't own the string; only the string information is copied.0.3670.3750.3652.881.23
stringa e = "Test text"; auto c{e};template<typename T> +
stringa e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { @@ -885,7 +885,7 @@ void CopyShortString(benchmark::State& state) { особенно если она инициализирована литералом. Copying a stringa is fast, especially if it is initialized with a literal.1.121.091.284.092.64
lstringa<20> e = "Test text"; auto c{e};template<typename T> +
lstringa<20> e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { @@ -895,7 +895,7 @@ void CopyShortString(benchmark::State& state) { } } >> В обоих случаях хватает внутреннего буфера. In both cases, the internal buffer is sufficient.4.124.524.777.6015.5
lstringa<40> e = "Test text"; auto c{e};template<typename T> +
lstringa<40> e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { @@ -916,7 +916,7 @@ Only bytes are copied.4.37
- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string e = "123456789012345678901234567890"; auto c{e};template<typename T> +
std::string e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { @@ -927,7 +927,7 @@ void CopyLongString(benchmark::State& state) { SSO уже не хватает. И снова как же отстаёт аллокация под Windows... Copying a long string causes allocations, SSO is no longer sufficient. And again, how allocation lags under Windows...20.123.570.677.936.8
std::string_view e = "123456789012345678901234567890"; auto c{e};template<typename T> +
std::string_view e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { @@ -935,7 +935,7 @@ void CopyLongString(benchmark::State& state) { benchmark::DoNotOptimize(copy); } }0.7320.7380.7262.041.25
ssa e = "123456789012345678901234567890"; auto c{e};template<typename T> +
ssa e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { @@ -943,7 +943,7 @@ void CopyLongString(benchmark::State& state) { benchmark::DoNotOptimize(copy); } }0.3760.7450.3622.070.975
stringa e = "123456789012345678901234567890"; auto c{e};template<typename T> +
stringa e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { @@ -954,7 +954,7 @@ void CopyLongString(benchmark::State& state) { сравни с предыдущим бенчмарком. But with stringa, literal copying doesn't depend on its length, compare with the previous benchmark.1.151.211.822.942.24
lstringa<20> e = "123456789012345678901234567890"; auto c{e};template<typename T> +
lstringa<20> e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { @@ -963,7 +963,7 @@ void CopyLongString(benchmark::State& state) { } } >> Не влезает, аллокация. Doesn't fit, allocation.21.522.477.580.515.9
lstringa<40> e = "123456789012345678901234567890"; auto c{e};template<typename T> +
lstringa<40> e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { @@ -983,7 +983,7 @@ Placed in the internal buffer.4.0

# Find 9 symbols text in end of 99 symbols text

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string::find;template<typename T> +
std::string::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { @@ -1001,7 +1001,7 @@ void Find(benchmark::State& state) { Однако, Windows и Linux явно в разных весовых категориях. Here, "friendship wins," with all types scoring roughly equally. However, Windows and Linux are clearly in different weight classes.6.676.9440.943.744.9
std::string_view::find;template<typename T> +
std::string_view::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { @@ -1016,7 +1016,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(x); } }7.816.6638.242.151.6
ssa::find;template<typename T> +
ssa::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { @@ -1031,7 +1031,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(x); } }7.116.5719.122.249.0
stringa::find;template<typename T> +
stringa::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { @@ -1046,7 +1046,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(x); } }7.186.6817.530.351.1
lstringa<20>::find;template<typename T> +
lstringa<20>::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { @@ -1061,7 +1061,7 @@ void Find(benchmark::State& state) { benchmark::DoNotOptimize(x); } }7.106.6018.220.443.9
lstringa<40>::find;template<typename T> +
lstringa<40>::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { @@ -1087,7 +1087,7 @@ void Find(benchmark::State& state) {

# Copy not literal Str with N symbols

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string copy{str_with_len_N};/15template<typename T> +
std::string copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1096,7 +1096,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }5.615.531.845.0435.7
std::string copy{str_with_len_N};/16template<typename T> +
std::string copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1110,7 +1110,7 @@ SSO у std::string меньше, насколько я помню, 11 симво The jump where SSO ends and allocation begins is clearly visible. Note that WASM is 32-bit, and the size of the SSO for std::string is smaller, as far as I remember: 11 characters + 0.23.023.779.181.535.9
std::string copy{str_with_len_N};/23template<typename T> +
std::string copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1120,7 +1120,7 @@ void CopyDynString(benchmark::State& state) { } } >> Дальше просто добавляется время на копирование байтов. Then the time for copying bytes is simply added.23.023.478.481.836.3
std::string copy{str_with_len_N};/24template<typename T> +
std::string copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1129,7 +1129,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }22.923.278.182.537.4
std::string copy{str_with_len_N};/32template<typename T> +
std::string copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1138,7 +1138,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }22.423.479.286.141.8
std::string copy{str_with_len_N};/64template<typename T> +
std::string copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1147,7 +1147,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }23.122.480.387.940.9
std::string copy{str_with_len_N};/128template<typename T> +
std::string copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1156,7 +1156,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }24.226.983.290.143.9
std::string copy{str_with_len_N};/256template<typename T> +
std::string copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1165,7 +1165,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }24.724.886.788.253.7
std::string copy{str_with_len_N};/512template<typename T> +
std::string copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1174,7 +1174,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }29.228.587.189.450.9
std::string copy{str_with_len_N};/1024template<typename T> +
std::string copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1183,7 +1183,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }45.346.798.295.258.1
std::string copy{str_with_len_N};/2048template<typename T> +
std::string copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1192,7 +1192,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }12312713113483.5
std::string copy{str_with_len_N};/4096template<typename T> +
std::string copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1202,7 +1202,7 @@ void CopyDynString(benchmark::State& state) { } } >> Чем длиннее строка, тем дольше создаётся копия. The longer the string, the longer it takes to create a copy.153155178184126
stringa copy{str_with_len_N};/15template<typename T> +
stringa copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1214,7 +1214,7 @@ void CopyDynString(benchmark::State& state) { а значит, должна сама хранить символы. Here, stringa is not initialized with a literal, meaning it must store characters itself.1.101.141.404.012.57
stringa copy{str_with_len_N};/16template<typename T> +
stringa copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1228,7 +1228,7 @@ void CopyDynString(benchmark::State& state) { Under WASM, stringa has a 15-character SSO. Furthermore, it was built without thread support, so the atomic increment was replaced with a regular one, judging by the time.1.111.141.383.994.88
stringa copy{str_with_len_N};/23template<typename T> +
stringa copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1240,7 +1240,7 @@ void CopyDynString(benchmark::State& state) { копируются быстрее, чем 15 в std::string. SSO in stringa is up to 23 characters, and even 23 copies faster than 15 in std::string.1.101.121.314.114.85
stringa copy{str_with_len_N};/24template<typename T> +
stringa copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1252,7 +1252,7 @@ void CopyDynString(benchmark::State& state) { Добавляется время на атомарный инкремент счётчика. That's it, we're not using SSO, so we're using a shared buffer. Time is added for the atomic counter increment.16.216.115.818.44.88
stringa copy{str_with_len_N};/32template<typename T> +
stringa copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1261,7 +1261,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }16.316.015.918.64.97
stringa copy{str_with_len_N};/64template<typename T> +
stringa copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1270,7 +1270,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }16.416.116.018.84.98
stringa copy{str_with_len_N};/128template<typename T> +
stringa copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1279,7 +1279,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }16.616.215.918.44.88
stringa copy{str_with_len_N};/256template<typename T> +
stringa copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1288,7 +1288,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }16.316.115.818.34.84
stringa copy{str_with_len_N};/512template<typename T> +
stringa copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1297,7 +1297,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }16.316.315.818.44.82
stringa copy{str_with_len_N};/1024template<typename T> +
stringa copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1306,7 +1306,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }16.416.015.818.34.85
stringa copy{str_with_len_N};/2048template<typename T> +
stringa copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1315,7 +1315,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }16.316.016.018.34.85
stringa copy{str_with_len_N};/4096template<typename T> +
stringa copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1327,7 +1327,7 @@ void CopyDynString(benchmark::State& state) { время копирования не зависит от длины строки. And as you can see, there are no overhead costs other than the increment; copying time does not depend on the string length.16.316.215.819.64.80
lstringa<16> copy{str_with_len_N};/15template<typename T> +
lstringa<16> copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1339,7 +1339,7 @@ void CopyDynString(benchmark::State& state) { А в WASM 32-битная архитектура, SSO до 19 символов. lstringa<16> uses SSO up to 23 characters. WASM has a 32-bit architecture, so SSO is up to 19 characters.4.194.484.587.2314.3
lstringa<16> copy{str_with_len_N};/16template<typename T> +
lstringa<16> copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1348,7 +1348,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }4.234.404.387.8914.7
lstringa<16> copy{str_with_len_N};/23template<typename T> +
lstringa<16> copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1357,7 +1357,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }4.114.564.497.6429.7
lstringa<16> copy{str_with_len_N};/24template<typename T> +
lstringa<16> copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1367,7 +1367,7 @@ void CopyDynString(benchmark::State& state) { } } >> И после начинает вести себя при копировании, как std::string. And then it starts to behave like std::string when copied.23.423.775.083.529.6
lstringa<16> copy{str_with_len_N};/32template<typename T> +
lstringa<16> copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1376,7 +1376,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }23.223.477.287.132.2
lstringa<16> copy{str_with_len_N};/64template<typename T> +
lstringa<16> copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1385,7 +1385,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }24.425.377.883.734.5
lstringa<16> copy{str_with_len_N};/128template<typename T> +
lstringa<16> copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1394,7 +1394,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }24.426.683.584.134.3
lstringa<16> copy{str_with_len_N};/256template<typename T> +
lstringa<16> copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1403,7 +1403,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }26.228.284.385.948.1
lstringa<16> copy{str_with_len_N};/512template<typename T> +
lstringa<16> copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1412,7 +1412,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }28.931.983.587.447.2
lstringa<16> copy{str_with_len_N};/1024template<typename T> +
lstringa<16> copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1421,7 +1421,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }93.796.493.896.453.7
lstringa<16> copy{str_with_len_N};/2048template<typename T> +
lstringa<16> copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1430,7 +1430,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }10710713213179.5
lstringa<16> copy{str_with_len_N};/4096template<typename T> +
lstringa<16> copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1439,7 +1439,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }121126188193123
lstringa<512> copy{str_with_len_N};/15template<typename T> +
lstringa<512> copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1448,7 +1448,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }4.495.384.868.0514.8
lstringa<512> copy{str_with_len_N};/16template<typename T> +
lstringa<512> copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1457,7 +1457,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }4.615.514.968.0615.7
lstringa<512> copy{str_with_len_N};/23template<typename T> +
lstringa<512> copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1466,7 +1466,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }4.755.674.868.2415.3
lstringa<512> copy{str_with_len_N};/24template<typename T> +
lstringa<512> copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1475,7 +1475,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }5.415.454.998.0215.2
lstringa<512> copy{str_with_len_N};/32template<typename T> +
lstringa<512> copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1484,7 +1484,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }4.775.078.6510.918.3
lstringa<512> copy{str_with_len_N};/64template<typename T> +
lstringa<512> copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1493,7 +1493,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }6.396.547.9910.818.2
lstringa<512> copy{str_with_len_N};/128template<typename T> +
lstringa<512> copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1502,7 +1502,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }6.257.268.0911.419.2
lstringa<512> copy{str_with_len_N};/256template<typename T> +
lstringa<512> copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1511,7 +1511,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }8.318.609.3012.419.6
lstringa<512> copy{str_with_len_N};/512template<typename T> +
lstringa<512> copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1523,7 +1523,7 @@ void CopyDynString(benchmark::State& state) { одна аллокация или атомарный инкремент. Even 512 characters are copied faster than a single allocation or atomic increment.10.111.511.014.222.9
lstringa<512> copy{str_with_len_N};/1024template<typename T> +
lstringa<512> copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1533,7 +1533,7 @@ void CopyDynString(benchmark::State& state) { } } >> А дальше уже как у всех. And then it's like everyone else.94.610899.199.557.1
lstringa<512> copy{str_with_len_N};/2048template<typename T> +
lstringa<512> copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1542,7 +1542,7 @@ void CopyDynString(benchmark::State& state) { benchmark::DoNotOptimize(x); } }10611013213279.9
lstringa<512> copy{str_with_len_N};/4096template<typename T> +
lstringa<512> copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { @@ -1604,7 +1604,7 @@ void CopyDynString(benchmark::State& state) {

# Convert to int '1234567'

- - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);void ToIntStr10(benchmark::State& state, const std::string& s, int c) { +
std::string s = "123456789"; int res = std::strtol(s.c_str(), 0, 10);void ToIntStr10(benchmark::State& state, const std::string& s, int c) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 10); #ifdef CHECK_RESULT @@ -1624,7 +1624,7 @@ In simstr, a string fragment is sufficient for conversion to a number; there's no need for null termination. The closest analog to this behavior is "std::from_chars," but unfortunately, it is very limited in its capabilities. Here, I attempted to run tests that are similar in logic to std::from_chars.27.127.930.732.171.7
std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);void ToIntFromChars10(benchmark::State& state, const std::string_view& s, int c) { +
std::string_view s = "123456789"; std::from_chars(s.data(), s.data() + s.size(), res, 10);void ToIntFromChars10(benchmark::State& state, const std::string_view& s, int c) { for (auto _: state) { int res = 0; std::from_chars(s.data(), s.data() + s.size(), res, 10); @@ -1640,7 +1640,7 @@ Here, I attempted to run tests that are similar in logic to std::from_chars.15.312.513.713.727.1
stringa s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> +
stringa s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> void ToIntSimStr10(benchmark::State& state, T t, int c) { for (auto _: state) { int res = t. template to_int<int, true, 10, false, false>().value; @@ -1657,7 +1657,7 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { десятичная система, без лидирующих пробелов и знака плюс Here, to_int has the same restrictions: check for overflow, decimal system, no leading spaces, and no plus sign.12.98.3214.414.618.7
ssa s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> +
ssa s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> void ToIntSimStr10(benchmark::State& state, T t, int c) { for (auto _: state) { int res = t. template to_int<int, true, 10, false, false>().value; @@ -1671,7 +1671,7 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(t); } }12.67.9213.715.117.0
lstringa<20> s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> +
lstringa<20> s = "123456789"; int res = s.to_int<int, true, 10, false>template<typename T> void ToIntSimStr10(benchmark::State& state, T t, int c) { for (auto _: state) { int res = t. template to_int<int, true, 10, false, false>().value; @@ -1695,7 +1695,7 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) {

# Convert to unsigned 'abcDef'

- - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);void ToIntStr16(benchmark::State& state, const std::string& s, int c) { +
std::string s = "abcDef"; int res = std::strtol(s.c_str(), 0, 16);void ToIntStr16(benchmark::State& state, const std::string& s, int c) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 16); #ifdef CHECK_RESULT @@ -1708,7 +1708,7 @@ void ToIntSimStr10(benchmark::State& state, T t, int c) { } } >> Всё то же, только для 16ричной системы Everything is the same, only for the hexadecimal system23.825.533.535.554.3
std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);void ToIntFromChars16(benchmark::State& state, const std::string_view& s, int c) { +
std::string_view s = "abcDef"; std::from_chars(s.data(), s.data() + s.size(), res, 16);void ToIntFromChars16(benchmark::State& state, const std::string_view& s, int c) { for (auto _: state) { int res = 0; std::from_chars(s.data(), s.data() + s.size(), res, 16); @@ -1721,7 +1721,7 @@ Everything is the same, only for the hexadecimal system9.6410.38.1013.228.7
stringa s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> +
stringa s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> void ToIntSimStr16(benchmark::State& state, T t, int c) { for (auto _: state) { int res = t. template to_int<int, true, 16, false, false>().value; @@ -1735,7 +1735,7 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(t); } }13.58.2312.014.017.7
ssa s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> +
ssa s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> void ToIntSimStr16(benchmark::State& state, T t, int c) { for (auto _: state) { int res = t. template to_int<int, true, 16, false, false>().value; @@ -1749,7 +1749,7 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(t); } }13.37.9912.013.816.0
lstringa<20> s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> +
lstringa<20> s = "abcDef"; int res = s.to_int<int, true, 16, false>template<typename T> void ToIntSimStr16(benchmark::State& state, T t, int c) { for (auto _: state) { int res = t. template to_int<int, true, 16, false, false>().value; @@ -1773,7 +1773,7 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) {

# Convert to int ' 1234567'

- - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);void ToIntStr0(benchmark::State& state, const std::string& s, int c) { +
std::string s = " 123456789"; int res = std::strtol(s.c_str(), 0, 0);void ToIntStr0(benchmark::State& state, const std::string& s, int c) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 0); #ifdef CHECK_RESULT @@ -1786,7 +1786,7 @@ void ToIntSimStr16(benchmark::State& state, T t, int c) { } } >> А здесь уже парсинг произвольного числа. And here we have parsing of an arbitrary number.28.528.843.544.681.3
stringa s = " 123456789"; int res = s.to_int<int>; // Check overflowtemplate<typename T> +
stringa s = " 123456789"; int res = s.to_int<int>; // Check overflowtemplate<typename T> void ToIntSimStr0(benchmark::State& state, T t, int c) { for (auto _: state) { int res = t. template to_int<int>().value; @@ -1800,7 +1800,7 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(t); } }19.115.117.719.024.5
ssa s = " 123456789"; int res = s.to_int<int, false>; // No check overflowvoid ToIntNoOverflow(benchmark::State& state, ssa t, int c) { +
ssa s = " 123456789"; int res = s.to_int<int, false>; // No check overflowvoid ToIntNoOverflow(benchmark::State& state, ssa t, int c) { for (auto _: state) { int res = t.to_int<int, false>().value; #ifdef CHECK_RESULT @@ -1821,7 +1821,7 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) {

# Convert to double '1234.567e10'

- - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);void ToDoubleStr(benchmark::State& state, const std::string& s, double c) { +
std::string s = "1234.567e10"; double res = std::strtod(s.c_str(), nullptr);void ToDoubleStr(benchmark::State& state, const std::string& s, double c) { for (auto _: state) { char* ptr = nullptr; double res = std::strtod(s.c_str(), &ptr); @@ -1837,7 +1837,7 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); } }66.365.110099.7197
std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);void ToDoubleFromChars(benchmark::State& state, const std::string_view& s, double c) { +
std::string_view s = "1234.567e10"; std::from_chars(s.data(), s.data() + s.size(), res);void ToDoubleFromChars(benchmark::State& state, const std::string_view& s, double c) { for (auto _: state) { double res = 0; if (std::from_chars(s.data(), s.data() + s.size(), res).ec != std::errc{}) { @@ -1852,7 +1852,7 @@ void ToIntSimStr0(benchmark::State& state, T t, int c) { benchmark::DoNotOptimize(res); } }23.923.859.380.0107
ssa s = "1234.567e10"; double res = *s.to_double()template<typename T> +
ssa s = "1234.567e10"; double res = *s.to_double()template<typename T> void ToDoubleSimStr(benchmark::State& state, T t, double c) { for (auto _: state) { auto r = t.template to_double<false>(); @@ -1878,7 +1878,7 @@ void ToDoubleSimStr(benchmark::State& state, T t, double c) {

# Append const literal of 16 bytes 64 times, 1024 total length

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::stringstream str; ... str << "abbaabbaabbaabba";void AppendStreamConstLiteral(benchmark::State& state) { +
std::stringstream str; ... str << "abbaabbaabbaabba";void AppendStreamConstLiteral(benchmark::State& state) { for (auto _: state) { std::string result; std::stringstream str; @@ -1896,7 +1896,7 @@ void ToDoubleSimStr(benchmark::State& state, T t, double c) { benchmark::DoNotOptimize(str); } }13431335482955334356
std::string str; ... str += "abbaabbaabbaabba";void AppendStdStringConstLiteral(benchmark::State& state) { +
std::string str; ... str += "abbaabbaabbaabba";void AppendStdStringConstLiteral(benchmark::State& state) { for (auto _: state) { std::string result; for (size_t c = 0; c < 64; c++) { @@ -1911,7 +1911,7 @@ void ToDoubleSimStr(benchmark::State& state, T t, double c) { benchmark::DoNotOptimize(result); } }40038010791309595
lstringa<8> str; ... str += "abbaabbaabbaabba";template<unsigned N> +
lstringa<8> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; @@ -1927,7 +1927,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); } }384394747947741
lstringa<128> str; ... str += "abbaabbaabbaabba";template<unsigned N> +
lstringa<128> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; @@ -1946,7 +1946,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { аллокация, тем быстрее результат. The larger the internal buffer, the fewer allocations are required, and the faster the result.282272391523571
lstringa<512> str; ... str += "abbaabbaabbaabba";template<unsigned N> +
lstringa<512> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; @@ -1962,7 +1962,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(result); } }255250238348464
lstringa<1024> str; ... str += "abbaabbaabbaabba";template<unsigned N> +
lstringa<1024> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; @@ -1989,7 +1989,7 @@ void AppendLstringConstLiteral(benchmark::State& state) {

# Append string of 16 bytes and const literal of 16 bytes 32 times, 1024 total length

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::stringstream str; ... str << str_var << "abbaabbaabbaabba";void AppendStreamStrConstLiteral(benchmark::State& state) { +
std::stringstream str; ... str << str_var << "abbaabbaabbaabba";void AppendStreamStrConstLiteral(benchmark::State& state) { std::string s1 = TEXT_16; for (auto _: state) { std::string result; @@ -2008,7 +2008,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(s1); } }14401363451258234443
std::string str; ... str += str_var + "abbaabbaabbaabba";void AppendStdStrStrConstLiteral(benchmark::State& state) { +
std::string str; ... str += str_var + "abbaabbaabbaabba";void AppendStdStrStrConstLiteral(benchmark::State& state) { std::string p1 = TEXT_16; for (auto _: state) { std::string result; @@ -2025,7 +2025,7 @@ void AppendLstringConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }12211255373040971968
lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> +
lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2043,7 +2043,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }444484702880921
lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> +
lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2061,7 +2061,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }366459448561694
lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> +
lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2079,7 +2079,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }297354298380656
lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> +
lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2108,7 +2108,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) {

# Append string of 16 bytes and const literal of 16 bytes 2048 times, 65536 total length

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 timesvoid AppendStreamStrConstLiteralBig(benchmark::State& state) { +
std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 timesvoid AppendStreamStrConstLiteralBig(benchmark::State& state) { std::string s1 = TEXT_16; for (auto _: state) { std::string result; @@ -2127,7 +2127,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(s1); } }7716973412217555307647223755
std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 timesvoid AppendStdStrStrConstLiteralBig(benchmark::State& state) { +
std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 timesvoid AppendStdStrStrConstLiteralBig(benchmark::State& state) { std::string p1 = TEXT_16; for (auto _: state) { std::string result; @@ -2144,7 +2144,7 @@ void AppendLstringStrConstLiteral(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }7373571780187292186310106717
lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> +
lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2162,7 +2162,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }2320921248191252402440706
lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> +
lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2180,7 +2180,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }1806017315167902228739893
lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> +
lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2198,7 +2198,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(p1); } }1994917550161822224039281
lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> +
lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { @@ -2227,7 +2227,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) {

# Append 2 string of 16 bytes 32 times, 1024 total length

- - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::stringstream str; ... str << str_var1 << str_var2;void AppendStream2String(benchmark::State& state) { +
std::stringstream str; ... str << str_var1 << str_var2;void AppendStream2String(benchmark::State& state) { std::string s1 = TEXT_16; std::string s2 = TEXT_16; for (auto _: state) { @@ -2248,7 +2248,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(s2); } }15271538436551934753
std::string str; ... str += str_var1 + str_var2;void AppendStdStr2String(benchmark::State& state) { +
std::string str; ... str += str_var1 + str_var2;void AppendStdStr2String(benchmark::State& state) { std::string s1 = TEXT_16; std::string s2 = TEXT_16; @@ -2268,7 +2268,7 @@ void AppendLstringStrConstLiteralBig(benchmark::State& state) { benchmark::DoNotOptimize(s2); } }14671325387840252557
lstringa<16> str; ... str += str_var1 + str_var2;template<unsigned N> +
lstringa<16> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; @@ -2288,7 +2288,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(s2); } }5325678589091248
lstringa<128> str; ... str += str_var1 + str_var2;template<unsigned N> +
lstringa<128> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; @@ -2308,7 +2308,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(s2); } }4664795986451085
lstringa<512> str; ... str += str_var1 + str_var2;template<unsigned N> +
lstringa<512> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; @@ -2328,7 +2328,7 @@ void AppendLstring2String(benchmark::State& state) { benchmark::DoNotOptimize(s2); } }413412388457934
lstringa<1024> str; ... str += str_var1 + str_var2;template<unsigned N> +
lstringa<1024> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; @@ -2359,7 +2359,7 @@ void AppendLstring2String(benchmark::State& state) {

# Append text, number, text

- - - - - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::stringstream str; str << "test = " << k << " times";void AppendStreamStrNumStr(benchmark::State& state) { +
std::stringstream str; str << "test = " << k << " times";void AppendStreamStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { std::stringstream t; @@ -2376,7 +2376,7 @@ void AppendLstring2String(benchmark::State& state) { } } }3076332310795111586507
std::string str = "test = " + std::to_string(k) + " times";void AppendStdStringStrNumStr(benchmark::State& state) { +
std::string str = "test = " + std::to_string(k) + " times";void AppendStdStringStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { std::string result = "test = " + std::to_string(k) + " times"; @@ -2391,7 +2391,7 @@ void AppendLstring2String(benchmark::State& state) { } } }494474108712311696
char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;void AppendSprintfStrNumStr(benchmark::State& state) { +
char buf[100]; sprintf(buf, "test = %u times", k); std::string str = buf;void AppendSprintfStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { char buf[100]; @@ -2408,7 +2408,7 @@ void AppendLstring2String(benchmark::State& state) { } } }14211486279428612885
std::string str = std::format("test = {} times", k);void AppendFormatStrNumStr(benchmark::State& state) { +
std::string str = std::format("test = {} times", k);void AppendFormatStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { std::string result = std::format("test = {} times", k); @@ -2423,7 +2423,7 @@ void AppendLstring2String(benchmark::State& state) { } } }11181312189725402102
lstringa<8> str; str.format("test = {} times", k);template<typename T> +
lstringa<8> str; str.format("test = {} times", k);template<typename T> void AppendSimStrStrNumStrF(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -2442,7 +2442,7 @@ void AppendSimStrStrNumStrF(benchmark::State& state) { } >> В simstr format с первого раза не помещается в такую строку без аллокации. In simstr format, the first time it doesn't fit into such a string without allocation.13741646207327563013
lstringa<32> str; str.format("test = {} times", k);template<typename T> +
lstringa<32> str; str.format("test = {} times", k);template<typename T> void AppendSimStrStrNumStrF(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -2460,7 +2460,7 @@ void AppendSimStrStrNumStrF(benchmark::State& state) { } } >> А в такую помещается. Используйте сразу буфера подходящего размера. And it fits in this one. Use buffers of the appropriate size right away.9741116110015282433
lstringa<8> str = "test = " + k + " times";template<typename T> +
lstringa<8> str = "test = " + k + " times";template<typename T> void AppendSimStrStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -2477,7 +2477,7 @@ void AppendSimStrStrNumStr(benchmark::State& state) { } } >> Результат не помещается в SSO, возникает аллокация. The result does not fit into SSO, an allocation occurs.296301867910641
lstringa<32> str = "test = " + k + " times";template<typename T> +
lstringa<32> str = "test = " + k + " times";template<typename T> void AppendSimStrStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -2496,7 +2496,7 @@ void AppendSimStrStrNumStr(benchmark::State& state) { Ещё раз - используйте сразу буфера подходящего размера. And here and below, the result fits within SSO. Once again, use appropriately sized buffers from the start.155146168183374
stringa str = "test = " + k + " times";template<typename T> +
stringa str = "test = " + k + " times";template<typename T> void AppendSimStrStrNumStr(benchmark::State& state) { for (auto _: state) { for (unsigned k = 1; k <= 1'000'000'000; k *= 10) { @@ -2529,7 +2529,7 @@ enough to accommodate the result, hence the long time.

# Split text and convert to int

- - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
std::string::find + substr + std::strtolvoid SplitConvertIntStdString(benchmark::State& state) { +
std::string::find + substr + std::strtolvoid SplitConvertIntStdString(benchmark::State& state) { std::string numbers = NUMBER_LIST; for (auto _: state) { int total = 0; @@ -2552,7 +2552,7 @@ enough to accommodate the result, hence the long time.281278550542643
ssa::splitter + ssa::as_intvoid SplitConvertIntSimStr(benchmark::State& state) { +
ssa::splitter + ssa::as_intvoid SplitConvertIntSimStr(benchmark::State& state) { stra numbers = NUMBER_LIST; for (auto _: state) { int total = 0; @@ -2569,7 +2569,7 @@ enough to accommodate the result, hence the long time.157139160294278
ssa::splitf + functorvoid SplitConvertIntSplitf(benchmark::State& state) { +
ssa::splitf + functorvoid SplitConvertIntSplitf(benchmark::State& state) { stra numbers = NUMBER_LIST; for (auto _: state) { int total = 0; @@ -2592,7 +2592,7 @@ enough to accommodate the result, hence the long time.

# Replace symbols in text ~400 symbols

- - - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Naive (and wrong) replace symbols with std::string find + replacevoid ReplaceSymbolsStdStringNaiveWrong(benchmark::State& state) { +
Naive (and wrong) replace symbols with std::string find + replacevoid ReplaceSymbolsStdStringNaiveWrong(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" @@ -2650,7 +2650,7 @@ enough to accommodate the result, hence the long time.'b' and 'b'->'a'. But if the substitutions don't conflict, it works quickly.1000826111813013545
replace symbols with std::string find_first_of + replacevoid ReplaceSymbolsStdStringNaiveRight(benchmark::State& state) { +
replace symbols with std::string find_first_of + replacevoid ReplaceSymbolsStdStringNaiveRight(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" @@ -2705,7 +2705,7 @@ it works quickly.1000 >> Дальше уже правильные реализации, не зависящие от конфликтующих замен. Further, there are correct implementations that do not depend on conflicting replacements.26792461199022254741
replace symbols with std::string_view find_first_of + copyvoid ReplaceSymbolsStdString(benchmark::State& state) { +
replace symbols with std::string_view find_first_of + copyvoid ReplaceSymbolsStdString(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" @@ -2757,7 +2757,7 @@ conflicting replacements.267911091030236925463504
replace runtime symbols with string expressions and without remembering all search resultstemplate<bool UseVector> +
replace runtime symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2803,7 +2803,7 @@ void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }12671459145416193605
replace runtime symbols with simstr and memorization of all search resultstemplate<bool UseVector> +
replace runtime symbols with simstr and memorization of all search resultstemplate<bool UseVector> void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2849,7 +2849,7 @@ void ReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }10021014139114343154
replace const symbols with string expressions and without remembering all search resultstemplate<bool UseVector> +
replace const symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2892,7 +2892,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); } }11501221122312772939
replace const symbols with string expressions and memorization of all search resultstemplate<bool UseVector> +
replace const symbols with string expressions and memorization of all search resultstemplate<bool UseVector> void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -2947,7 +2947,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) {

# Replace symbols in text ~40 symbols

- - - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Short Naive (and wrong) replace symbols with std::string find + replacevoid ShortReplaceSymbolsStdStringNaiveWrong(benchmark::State& state) { +
Short Naive (and wrong) replace symbols with std::string find + replacevoid ShortReplaceSymbolsStdStringNaiveWrong(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" ; @@ -2986,7 +2986,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }172161319332436
Short replace symbols with std::string find_first_of + replacevoid ShortReplaceSymbolsStdStringNaiveRight(benchmark::State& state) { +
Short replace symbols with std::string find_first_of + replacevoid ShortReplaceSymbolsStdStringNaiveRight(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" ; @@ -3025,7 +3025,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }322353371428510
Short replace symbols with std::string_view find_first_of + copyvoid ShortReplaceSymbolsStdString(benchmark::State& state) { +
Short replace symbols with std::string_view find_first_of + copyvoid ShortReplaceSymbolsStdString(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" ; @@ -3063,7 +3063,7 @@ void ReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); } }167171327356440
Short replace runtime symbols with string expressions and without remembering all search resultstemplate<bool UseVector> +
Short replace runtime symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -3095,7 +3095,7 @@ void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }181192268319386
Short replace runtime symbols with simstr and memorization of all search resultstemplate<bool UseVector> +
Short replace runtime symbols with simstr and memorization of all search resultstemplate<bool UseVector> void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -3127,7 +3127,7 @@ void ShortReplaceSymbolsDynPatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }185195388383420
Short replace const symbols with string expressions and without remembering all search resultstemplate<bool UseVector> +
Short replace const symbols with string expressions and without remembering all search resultstemplate<bool UseVector> void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -3156,7 +3156,7 @@ void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { benchmark::DoNotOptimize(source); } }144178241267260
Short replace const symbols with string expressions and memorization of all search resultstemplate<bool UseVector> +
Short replace const symbols with string expressions and memorization of all search resultstemplate<bool UseVector> void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) { stra source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" @@ -3197,7 +3197,7 @@ void ShortReplaceSymbolsCons2PatternSimStr(benchmark::State& state) {

# Replace All Str To Longer Size

- - - - - - - - - - - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
replace bb to ---- in std::string|64template<size_t Long> +
replace bb to ---- in std::string|64template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3230,7 +3230,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }156183240275377
replace bb to ---- in std::string|256template<size_t Long> +
replace bb to ---- in std::string|256template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3263,7 +3263,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }5254998588991421
replace bb to ---- in std::string|512template<size_t Long> +
replace bb to ---- in std::string|512template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3296,7 +3296,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }10421012144616322623
replace bb to ---- in std::string|1024template<size_t Long> +
replace bb to ---- in std::string|1024template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3329,7 +3329,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }24182304319433185482
replace bb to ---- in std::string|2048template<size_t Long> +
replace bb to ---- in std::string|2048template<size_t Long> void ReplaceAllLongerStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3362,7 +3362,7 @@ void ReplaceAllLongerStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }588357967825811613478
replace bb to ---- in lstringa<8>|64template<size_t N, size_t Count> +
replace bb to ---- in lstringa<8>|64template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3384,7 +3384,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }144154224235311
replace bb to ---- in lstringa<8>|256template<size_t N, size_t Count> +
replace bb to ---- in lstringa<8>|256template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3406,7 +3406,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }5294846196861149
replace bb to ---- in lstringa<8>|512template<size_t N, size_t Count> +
replace bb to ---- in lstringa<8>|512template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3428,7 +3428,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }880886108311082165
replace bb to ---- in lstringa<8>|1024template<size_t N, size_t Count> +
replace bb to ---- in lstringa<8>|1024template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3450,7 +3450,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }18051917188620423868
replace bb to ---- in lstringa<8>|2048template<size_t N, size_t Count> +
replace bb to ---- in lstringa<8>|2048template<size_t N, size_t Count> void ReplaceAllLongerSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3472,7 +3472,7 @@ void ReplaceAllLongerSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }32653636362539337737
replace bb to ---- by init stringa|64template<size_t Count> +
replace bb to ---- by init stringa|64template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3493,7 +3493,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(source); } }10799.5177205226
replace bb to ---- by init stringa|256template<size_t Count> +
replace bb to ---- by init stringa|256template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3514,7 +3514,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(source); } }313297371475790
replace bb to ---- by init stringa|512template<size_t Count> +
replace bb to ---- by init stringa|512template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3535,7 +3535,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(source); } }75171781310391685
replace bb to ---- by init stringa|1024template<size_t Count> +
replace bb to ---- by init stringa|1024template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3556,7 +3556,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(source); } }16571663163421653603
replace bb to ---- by init stringa|2048template<size_t Count> +
replace bb to ---- by init stringa|2048template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; @@ -3597,7 +3597,7 @@ void ReplaceAllLongerSimStringExpr(benchmark::State& state) {

# Replace All Str To Same Size

- - - - - - - - - - - - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
replace bb to -- in std::string|64template<size_t Long> +
replace bb to -- in std::string|64template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3629,7 +3629,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }120123195212268
replace bb to -- in std::string|256template<size_t Long> +
replace bb to -- in std::string|256template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3661,7 +3661,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }404383477528987
replace bb to -- in std::string|512template<size_t Long> +
replace bb to -- in std::string|512template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3693,7 +3693,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }7617198759691942
replace bb to -- in std::string|1024template<size_t Long> +
replace bb to -- in std::string|1024template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3725,7 +3725,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }16061415163018203660
replace bb to -- in std::string|2048template<size_t Long> +
replace bb to -- in std::string|2048template<size_t Long> void ReplaceAllEqualStdString(benchmark::State& state) { std::string_view source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; std::string_view sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3757,7 +3757,7 @@ void ReplaceAllEqualStdString(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }32802838327835857038
replace bb to -- in lstringa<8>|64template<size_t N, size_t Long> +
replace bb to -- in lstringa<8>|64template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3778,7 +3778,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }104102182190229
replace bb to -- in lstringa<8>|256template<size_t N, size_t Long> +
replace bb to -- in lstringa<8>|256template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3799,7 +3799,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }312300440475776
replace bb to -- in lstringa<8>|512template<size_t N, size_t Long> +
replace bb to -- in lstringa<8>|512template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3820,7 +3820,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }5915628479041461
replace bb to -- in lstringa<8>|1024template<size_t N, size_t Long> +
replace bb to -- in lstringa<8>|1024template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3841,7 +3841,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }11391116158016262897
replace bb to -- in lstringa<8>|2048template<size_t N, size_t Long> +
replace bb to -- in lstringa<8>|2048template<size_t N, size_t Long> void ReplaceAllEqualSimString(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3862,7 +3862,7 @@ void ReplaceAllEqualSimString(benchmark::State& state) { benchmark::DoNotOptimize(source); } }26792185282831525674
replace bb to -- by init stringa|64template<size_t Count> +
replace bb to -- by init stringa|64template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3887,7 +3887,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }91.097.1153172187
replace bb to -- by init stringa|256template<size_t Count> +
replace bb to -- by init stringa|256template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3912,7 +3912,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }242274355397652
replace bb to -- by init stringa|512template<size_t Count> +
replace bb to -- by init stringa|512template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3937,7 +3937,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }4315445996731221
replace bb to -- by init stringa|1024template<size_t Count> +
replace bb to -- by init stringa|1024template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -3962,7 +3962,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { benchmark::DoNotOptimize(repl); } }9141481107712582366
replace bb to -- by init stringa|2048template<size_t Count> +
replace bb to -- by init stringa|2048template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; @@ -4007,7 +4007,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) {

# Hash Map insert and find

- - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
hashStrMapA<size_t> emplace & find stringa;void HashMapSimStr(benchmark::State& state) { +
hashStrMapA<size_t> emplace & find stringa;void HashMapSimStr(benchmark::State& state) { for (auto _: state) { hashStrMapA<size_t> store; for (size_t idx = 0; idx < bs_sim.size(); idx++) { @@ -4033,7 +4033,7 @@ void ReplaceAllEqualSimStringExpr(benchmark::State& state) { символов, а потом ищем их в ней We insert 10,000 strings of length from 30 to 50 characters into hashStrMapA, and then search for them in it.35464283640422397835043612653192661
std::unordered_map<std::string, size_t> emplace & find std::string;void HashMapStdStr(benchmark::State& state) { +
std::unordered_map<std::string, size_t> emplace & find std::string;void HashMapStdStr(benchmark::State& state) { for (auto _: state) { std::unordered_map<std::string, size_t> store; for (size_t idx = 0; idx < bs_std.size(); idx++) { @@ -4057,7 +4057,7 @@ hashStrMapA, and then search for them in it. >> То же самое c std::string и std::unordered_map Same thing with std::string and std::unordered_map34869753537855560756758784633399083
hashStrMapA<size_t> emplace & find ssa;void HashMapSimSsa(benchmark::State& state) { +
hashStrMapA<size_t> emplace & find ssa;void HashMapSimSsa(benchmark::State& state) { for (auto _: state) { hashStrMapA<size_t> store; for (size_t idx = 0; idx < bs_sim.size(); idx++) { @@ -4082,7 +4082,7 @@ Same thing with std::string and std::unordered_map >> Теперь вставляем stringa, а ищем ssa Now we insert stringa and search for ssa35925443721221348921139458923300905
std::unordered_map<std::string, size_t> emplace & find std::string_view;void HashMapStdStrView(benchmark::State& state) { +
std::unordered_map<std::string, size_t> emplace & find std::string_view;void HashMapStdStrView(benchmark::State& state) { for (auto _: state) { std::unordered_map<std::string, size_t> store; for (size_t idx = 0; idx < bs_std.size(); idx++) { @@ -4116,7 +4116,7 @@ We insert std::string and look for std::string_view

# Build Full Func Name

- - - - -
Benchmark nameCommentXeon E5-2682 v4, Ubuntu 22 (WSL), Clang-21Xeon E5-2682 v4, Ubuntu 22 (WSL), GCC-13Xeon E5-2682 v4, Windows 10, Clang-19Xeon E5-2682 v4, Windows 10, MSVC-19Xeon E5-2682 v4, WASM Firefox, Clang-21
Build func full name std::string;std::string build_full_name_std() const { +
Build func full name std::string;std::string build_full_name_std() const { std::string str{has_ret_type_resolver ? "any"sv : type_names_sv[(unsigned)ret_type]}; str += " "; str += std_name; @@ -4154,7 +4154,7 @@ A common task, similar to this one, can often be encountered in work: Generate text from given data. In this case, using data on certain functions, generate their full names with parameter types and return values. The algorithm uses std::string.697916150716443032
Build func full name std::string 1;std::string build_full_name_std1() const { +
Build func full name std::string 1;std::string build_full_name_std1() const { std::string str{has_ret_type_resolver ? "any"sv : type_names_sv[(unsigned)ret_type]}; str += " " + std_name + "("; @@ -4186,7 +4186,7 @@ return values. The algorithm uses std::string.8031081154317493434
Build func full name std::stream;std::string build_full_name_stream() const { +
Build func full name std::stream;std::string build_full_name_stream() const { std::ostringstream str; if (has_ret_type_resolver) { str << "any"; @@ -4220,7 +4220,7 @@ Almost the same algorithm, but several consecutive return str.str(); } >> Строим имя функции через std::ostringstream и << We construct the function name through std::ostringstream and <<25402581808799407330
Build func full name stringa;stringa build_full_name() const { +
Build func full name stringa;stringa build_full_name() const { lstringa<512> str = e_choice(has_ret_type_resolver, "any", type_names[(unsigned)ret_type]) + " " + name + "("; bool add_comma = false; @@ -4238,7 +4238,7 @@ We construct the function name through std::ostringstream and <<5074788239371429
Build func full name stringa 1;stringa build_full_name1() const { +
Build func full name stringa 1;stringa build_full_name1() const { lstringa<512> str = e_choice(has_ret_type_resolver, "any", type_names[(unsigned)ret_type]) + " " + name + "("; bool add_comma = false;