simstr benchmarks results

simstr is a powerful and convenient library for productive work with strings in C++.
All times in ns. Source for benchmarks
Group tests by platforms in charts:

Test configurations:

# Concatenate email

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 Chrome 143, Clang-21
Concat email std::formatstd::string email_concat_format(std::string_view name, std::string_view domain, std::string_view tld) { return std::format("{}@{}.{}", name, domain, tld); }170190205253993
Concat email std::stringstreamstd::string email_concat_stream(std::string_view name, std::string_view domain, std::string_view tld) { std::stringstream s; s << name << "@" << domain << "." << tld; return s.str(); }3253248339462513
Concat email stringzilla appendsz::string email_concat_stringzilla_app(sz::string name, sz::string_view domain, sz::string_view tld) { return name.append("@").append(domain).append(".").append(tld); }142120267289574
Concat email stringzilla concatsz::string email_concat_stringzilla_exp(sz::string name, sz::string_view domain, sz::string_view tld) { return sz::string{name | sz::string_view{"@"} | domain | sz::string_view{"."} | tld}; } >> В stringzilla тоже есть конкатенация строковыми выражениями, но не так удобна и развита, как в simstr. Stringzilla also has concatenation by expression templates, but it's not as convenient or advanced as simstr.53.149.2127134222
Concat email std::string appendstd::string email_concat_std(std::string name, std::string_view domain, std::string_view tld) { return name.append("@").append(domain).append(".").append(tld); }72.998.9184194636
Concat email std::string by strexprstd::string email_concat_std_expr(std::string_view name, std::string_view domain, std::string_view tld) { return +name + "@" + domain + "." + tld; }43.537.6113112159
Concat email stringastringa email_concat_sim_expr(ssa name, ssa domain, ssa tld) { return name + "@" + domain + "." + tld; }38.940.996.298.1133

# 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 Chrome 143, Clang-21
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) { benchmark::DoNotOptimize(s1); std::string str = s1 + std::to_string(i) + " end"; benchmark::DoNotOptimize(str); } } }2202232713141951
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) { benchmark::DoNotOptimize(s1); std::string str = +s1 + i + " end"; benchmark::DoNotOptimize(str); } } }104102162206974
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) { benchmark::DoNotOptimize(s1); stringa str = s1 + i + " end"; benchmark::DoNotOptimize(str); } } } >> stringa в отличии от std::string, вмещает в SSO 23 символа вместо 15, поэтому в конце теста std::string приходится аллоцировать память, а в stringa весь тест входит в SSO. 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.65.373.671.6102369
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) { benchmark::DoNotOptimize(s1); stringa str = e_concat("", s1, i, " end"); benchmark::DoNotOptimize(str); } } }69.778.574.8109367

# 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 Chrome 143, Clang-21
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); // It is not worked for char8_t, char16_t, char32_t :( std::string str = s1 + std::format("{:#x}", i) + " end"; benchmark::DoNotOptimize(str); } } }69269571310733765
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); // It is not worked for char8_t, char16_t, char32_t :( std::string str = std::format("{}{:#x} end", s1, i); benchmark::DoNotOptimize(str); } } }922995154418434994
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); // it worked only for char :( char buf[40]; size_t len = std::to_chars(buf, buf + std::size(buf), i, 16).ptr - buf; std::string str = s1 + "0x" + std::string(buf, len) + " end"; benchmark::DoNotOptimize(str); } } }1982501922551114
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); // Can work for all types of symbols std::string str = +s1 + i / 1_f16 + " end"; benchmark::DoNotOptimize(str); } } }13212591.6114885
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); // Can work for all types of symbols stringa str = s1 + i / 1_f16 + " end"; benchmark::DoNotOptimize(str); } } }11612272.9102252
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); // Can work for all types of symbols stringa str = e_concat("", s1, i / 1_f16, " end"); benchmark::DoNotOptimize(str); } } }12412877.5104276
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); stringa str = e_subst("{}{} end", s1, i / 1_f16); benchmark::DoNotOptimize(str); } } }181174154176548
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) { for (unsigned i = 1; i <= 100'000; i *= 10) { benchmark::DoNotOptimize(s1); stringa str = e_vsubst("{}{} end"_ss, s1, i / 1_f16); benchmark::DoNotOptimize(str); } } }3123042873651724

# format/vformat and subst/vsubst octal number to 32 symbols result

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 Chrome 143, Clang-21
"abcdefghihklmopqr "_ss + i / 0x8a010_fmt + " end"void ConcatSimToSimOct(benchmark::State& state) { for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { stringa str = "abcdefghihklmopqr "_ss + i / 0x8a010_fmt + " end"; benchmark::DoNotOptimize(str); } } }276264671682930
e_subst("abcdefghihklmopqr {} end", i / 0x8a010_fmt)void SubstSimToSimOct(benchmark::State& state) { for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { stringa str = e_subst("abcdefghihklmopqr {} end", i / 0x8a010_fmt); benchmark::DoNotOptimize(str); } } }3523187507981123
e_vsubst(pattern, i / 0x8a010_fmt)void VSubstSimToSimOct(benchmark::State& state) { ssa pattern = "abcdefghihklmopqr {} end"; for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { stringa str = e_vsubst(pattern, i / 0x8a010_fmt); benchmark::DoNotOptimize(str); } } }616583108111282923
fmt::format(FMT_COMPILE("abcdefghihklmopqr {:#010o} end"), i)void FmtFormatComp(benchmark::State& state) { for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { std::string str = fmt::format(FMT_COMPILE("abcdefghihklmopqr {:#010o} end"), i); benchmark::DoNotOptimize(str); } } }755809144915774411
fmt::format("abcdefghihklmopqr {:#010o} end", i)void FmtFormat(benchmark::State& state) { for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { std::string str = fmt::format("abcdefghihklmopqr {:#010o} end", i); benchmark::DoNotOptimize(str); } } }894882136415354578
std::format("abcdefghihklmopqr {:#010o} end", i)void FormatStdToStdOct(benchmark::State& state) { for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { std::string str = std::format("abcdefghihklmopqr {:#010o} end", i); benchmark::DoNotOptimize(str); } } }9921261169919315729
std::vformat(pattern, std::make_format_args(i))void VFormatStdToStdOct(benchmark::State& state) { std::string_view pattern = "abcdefghihklmopqr {:#010o} end"; for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { std::string str = std::vformat(pattern, std::make_format_args(i)); benchmark::DoNotOptimize(str); } } }10001151158619145777
strm << "abcdefghihklmopqr 0" << std::oct << std::setw(9) << std::setfill('0') << i << " end"void StreamStdToStdOct(benchmark::State& state) { for (auto _: state) { for (unsigned i = 1; i <= 100'000; i *= 10) { std::stringstream strm; strm << "abcdefghihklmopqr 0" << std::oct << std::setw(9) << std::setfill('0') << i << " end"; std::string str = strm.str(); benchmark::DoNotOptimize(str); } } }205521336885706218843

# 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 Chrome 143, Clang-21
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) { benchmark::DoNotOptimize(s1); std::string str = s1 + " end"; benchmark::DoNotOptimize(str); } } }44.349.840.855.6155
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) { benchmark::DoNotOptimize(s1); std::string str = +s1 + " end"; benchmark::DoNotOptimize(str); } } }31.332.338.279.3175
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) { benchmark::DoNotOptimize(s1); stringa str = s1 + " end"; benchmark::DoNotOptimize(str); } } }28.426.428.750.7146

# 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 Chrome 143, Clang-21
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"); }114146208219501
Find concat three strexprsize_t find_pos_exp(ssa src, ssa name) { return src.find(std::string{"\n- " + name + " -\n"}); }49.339.0114125288
Find concat three simstrsize_t find_pos_sim(ssa src, ssa name) { return src.find(lstringa<200>{"\n- " + name + " -\n"}); } >> Если результат конкатенации меньше 207 символов, он собирается в буфере на стеке, без аллокации и деалокации. If the concatenation result is less than 207 characters, it is collected in a stack-based buffer, without allocation or deallocation.19.416.421.528.4174
Find concat three stringzilla stringsize_t find_pos_sz(sz::string_view src, sz::string_view name) { return src.find(sz::string{"\n- "}.append(name).append(" -\n")); }143139214228621

# 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 Chrome 143, Clang-21
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); if (scale) { res += "," + std::to_string(scale); } res += ")"; } return res; }7.0910.88.4017.427.5
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.908.497.4312.829.2
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.954.967.8015.138.8
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); if (scale) { res += "," + std::to_string(scale); } res += ")"; } return res; }56.387.258.877.5661
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; }31.026.832.139.5201
BuildTypeNameSim 10/10stringa buildTypeNameSim(ssa type_name, size_t prec, size_t scale) { if (prec) { return type_name + "(" + prec + e_if(scale, ","_ss + scale) + ")"; } return type_name; }22.823.225.638.3105

# 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 Chrome 143, Clang-21
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; ;) { size_t pos = from.find(pattern, offset); if (pos == std::string::npos) { result += from.substr(offset); break; } result += from.substr(offset, pos - offset); result += repl; offset = pos + pattern.length(); } return result; }; return "<" + str_replace(from, pattern, repl) + ">"; }2132353093431091
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 строковое выражение для замены подстрок есть "из коробки". simstr has a string expression for replacing substrings out of the box.147142217225502

# 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 Chrome 143, Clang-21
std::string e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } } >> Пустые строки, ничего необычного. Empty lines, nothing unusual.1.111.141.102.592.63
std::string_view e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }0.3690.7700.3661.842.19
ssa e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }0.3710.1880.3641.842.14
stringa e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }0.7580.7770.7452.202.97
lstringa<20> e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }1.141.141.122.583.67
lstringa<40> e;template<typename T> void CreateEmpty(benchmark::State& state) { for (auto _: state) { T empty_string; benchmark::DoNotOptimize(empty_string); } }1.151.181.162.543.54

# 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 Chrome 143, Clang-21
std::string e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } } >> Короткий литерал помещается во внутренний буфер std::string, время тратится только на копирование 10 байтов. The short literal is placed in the internal std::string buffer; time is spent only copying 10 bytes.1.851.911.852.533.39
std::string_view e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } } >> И string_view, и ssa - по сути одно и то же: указатель на текст и его длина. Both string_view and ssa are essentially the same thing: a pointer to text and its length.0.7600.7650.7361.842.19
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.3800.7650.3631.822.14
stringa e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } } >> stringa при инициализации константным литералом так же сохраняет только указатель на текст и его длину. When initialized with a constant literal, stringa also stores only a pointer to the text and its length.1.131.131.113.043.03
lstringa<20> e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } } >> Внутреннего буфера хватает для размещения символов, время уходит только на копирование байтов. The internal buffer is sufficient to accommodate characters; time is spent only on copying bytes.1.911.901.852.573.96
lstringa<40> e = "Test text";template<typename T> void CreateShortLiteral(benchmark::State& state) { for (auto _: state) { T empty_string = TEST_TEXT; benchmark::DoNotOptimize(empty_string); } }1.831.921.842.623.99

# Create Str from long literal (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 Chrome 143, Clang-21
std::string e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } } >> Вот тут уже литерал не помещается во внутренний буфер, возникает аллокация и копирование 30-и байтов. Но как же отстает аллокация под Windows от Linux'а, 20 vs 70 ns... 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...21.720.276.077.269.1
std::string_view e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } } >> string_view и ssa по прежнему ничего не делают, кроме запоминания указателя на текст и его размера. string_view and ssa still do nothing except remember the pointer to the text and its size.0.7350.7590.7351.842.17
ssa e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } }0.3830.7670.3641.842.14
stringa e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } } >> stringa на константных литералах не отстает! stringa doesn't lag behind on constant literals!1.101.201.102.202.97
lstringa<20> e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } } >> lstringa<20> может вместить в себя до 23 символов, Очевидно, что для 30-и символов уже нужна аллокация. Obviously, 30 characters already require allocation.21.024.073.774.569.7
lstringa<40> e = "123456789012345678901234567890";template<typename T> void CreateLongLiteral(benchmark::State& state) { for (auto _: state) { T empty_string{LONG_TEXT}; benchmark::DoNotOptimize(empty_string); } } >> А в lstringa<40> влезает до 47 символов, так что просто копируется 30 байтов. And lstringa<40> can hold up to 47 characters, so 30 bytes are simply copied.2.591.942.543.3416.5

# 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 Chrome 143, Clang-21
std::string e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Строка в пределах SSO, так что просто копирует байты. The string is within the SSO, so it just copies the bytes.5.275.671.835.366.73
std::string_view e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }0.3830.3780.3662.922.20
ssa e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> ssa и string_view не владеют строкой, копируется только информация о строке. ssa and string_view don't own the string; only the string information is copied.0.3760.3910.3642.922.21
stringa e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Копирование stringa происходит быстро, особенно если она инициализирована литералом. Copying a stringa is fast, especially if it is initialized with a literal.1.111.121.314.114.66
lstringa<20> e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> В обоих случаях хватает внутреннего буфера. In both cases, the internal buffer is sufficient.1.501.141.474.717.15
lstringa<40> e = "Test text"; auto c{e};template<typename T> void CopyShortString(benchmark::State& state) { T x{TEST_TEXT}; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Только копируются байты. Only bytes are copied.1.521.151.485.447.34

# 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 Chrome 143, Clang-21
std::string e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); } } >> Копирования длинной строки вызывает аллокацию, SSO уже не хватает. И снова как же отстаёт аллокация под Windows... Copying a long string causes allocations, SSO is no longer sufficient. And again, how allocation lags under Windows...19.124.672.478.7119
std::string_view e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); } }0.7520.7750.7341.492.22
ssa e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); } }0.3750.7470.3641.522.16
stringa e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); } } >> А вот у stringa копирование литерала не зависит от его длины, сравни с предыдущим бенчмарком. But with stringa, literal copying doesn't depend on its length, compare with the previous benchmark.1.111.191.842.932.98
lstringa<20> e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); } } >> Не влезает, аллокация. Doesn't fit, allocation.21.520.475.779.572.7
lstringa<40> e = "123456789012345678901234567890"; auto c{e};template<typename T> void CopyLongString(benchmark::State& state) { T x = LONG_TEXT; for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); } } >> Уложили во внутренний буфер. Placed in the internal buffer.4.614.844.847.3750.4

# 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 Chrome 143, Clang-21
sz::string::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { int i = (int)x.find(TEST_TEXT); #ifdef CHECK_RESULT if (i != 90) { state.SkipWithError("not find?"); break; } #endif benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } } >> stringzilla более заточена на поиск больших строк в больших строках. stringzilla is more focused on searching large strings within large strings.95.095.398.2117231
std::string::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { int i = (int)x.find(TEST_TEXT); #ifdef CHECK_RESULT if (i != 90) { state.SkipWithError("not find?"); break; } #endif benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } } >> Здесь "победила дружба", у всех типов по колонке примерно одинаково. Однако, Windows и Linux явно в разных весовых категориях. Here, "friendship wins," with all types scoring roughly equally. However, Windows and Linux are clearly in different weight classes.7.296.9539.939.299.9
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) { int i = (int)x.find(TEST_TEXT); #ifdef CHECK_RESULT if (i != 90) { state.SkipWithError("not find?"); break; } #endif benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } }7.548.1952.239.096.4
ssa::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { int i = (int)x.find(TEST_TEXT); #ifdef CHECK_RESULT if (i != 90) { state.SkipWithError("not find?"); break; } #endif benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } }7.606.9918.921.997.9
stringa::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { int i = (int)x.find(TEST_TEXT); #ifdef CHECK_RESULT if (i != 90) { state.SkipWithError("not find?"); break; } #endif benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } }8.426.9119.431.099.1
lstringa<20>::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { int i = (int)x.find(TEST_TEXT); #ifdef CHECK_RESULT if (i != 90) { state.SkipWithError("not find?"); break; } #endif benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } }6.846.6517.621.9115
lstringa<40>::find;template<typename T> void Find(benchmark::State& state) { T x{LONG_TEXT LONG_TEXT LONG_TEXT TEST_TEXT}; for (auto _: state) { int i = (int)x.find(TEST_TEXT); #ifdef CHECK_RESULT if (i != 90) { state.SkipWithError("not find?"); break; } #endif benchmark::DoNotOptimize(i); benchmark::DoNotOptimize(x); } }6.916.5818.022.2115

# 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 Chrome 143, Clang-21
std::string copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }5.959.011.855.24125
std::string copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Явно виден скачок, где заканчивается SSO и начинается аллокация. Обратите внимание, что WASM - 32-битный, и там размер SSO у std::string меньше, 10 символов + 0. 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.328.578.879.3125
std::string copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Дальше просто добавляется время на копирование байтов. Then the time for copying bytes is simply added.23.827.877.277.7126
std::string copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }23.528.877.577.5120
std::string copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }24.027.383.086.2124
std::string copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }23.127.081.280.0123
std::string copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }25.329.283.884.8133
std::string copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }31.434.288.088.0156
std::string copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }28.834.092.588.8150
std::string copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }34.937.710297.7174
std::string copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }81.281.1123135217
std::string copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Чем длиннее строка, тем дольше создаётся копия. The longer the string, the longer it takes to create a copy.120120175183263
stringa copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Здесь stringa инициализируется не литералом, а значит, должна сама хранить символы. Here, stringa is not initialized with a literal, meaning it must store characters itself.1.091.351.294.094.83
stringa copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Под WASM SSO у stringa составляет 15 символов. Кроме того, собиралось без поддержки потоков, поэтому атомарный инкремент заменён на обычный, судя по времени. 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.101.341.294.087.81
stringa copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> SSO в stringa до 23 символов, и даже 23 копируются быстрее, чем 15 в std::string. SSO in stringa is up to 23 characters, and even 23 copies faster than 15 in std::string.1.121.321.313.998.12
stringa copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Всё, не влезаем в SSO, а значит, используем shared буфер. Добавляется время на атомарный инкремент счётчика. That's it, we're not using SSO, so we're using a shared buffer. Time is added for the atomic counter increment.16.116.715.918.67.86
stringa copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }16.016.417.418.57.82
stringa copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }16.316.416.018.67.90
stringa copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }16.116.516.018.57.78
stringa copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }16.116.416.018.78.03
stringa copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }16.016.416.018.67.91
stringa copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }16.216.616.018.67.78
stringa copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }16.216.716.018.57.80
stringa copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> И как видно, кроме инкремента нет накладных расходов, время копирования не зависит от длины строки. And as you can see, there are no overhead costs other than the increment; copying time does not depend on the string length.16.016.916.018.67.79
lstringa<16> copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> lstringa<16> использует SSO до 23 символов. А в 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.1.521.161.524.088.00
lstringa<16> copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }4.834.985.178.4820.7
lstringa<16> copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }4.815.055.128.5088.9
lstringa<16> copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> И после начинает вести себя при копировании, как std::string. And then it starts to behave like std::string when copied.25.024.677.978.688.3
lstringa<16> copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }25.124.483.583.292.9
lstringa<16> copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }27.426.284.684.096.1
lstringa<16> copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }27.127.684.687.197.2
lstringa<16> copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }28.127.885.790.7130
lstringa<16> copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }30.731.087.189.3116
lstringa<16> copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }52.955.096.6101139
lstringa<16> copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }67.664.4125125178
lstringa<16> copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }87.890.0180190221
lstringa<512> copy{str_with_len_N};/15template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }1.581.131.454.828.09
lstringa<512> copy{str_with_len_N};/16template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }4.904.485.219.2121.2
lstringa<512> copy{str_with_len_N};/23template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }4.834.495.189.4220.4
lstringa<512> copy{str_with_len_N};/24template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }4.784.105.219.4920.3
lstringa<512> copy{str_with_len_N};/32template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }4.594.408.1912.222.6
lstringa<512> copy{str_with_len_N};/64template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }6.155.648.2112.223.3
lstringa<512> copy{str_with_len_N};/128template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }7.027.258.4812.724.5
lstringa<512> copy{str_with_len_N};/256template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }8.437.909.7913.626.6
lstringa<512> copy{str_with_len_N};/512template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> Даже 512 символов копируются быстрее, чем одна аллокация или атомарный инкремент. Even 512 characters are copied faster than a single allocation or atomic increment.11.510.411.215.428.5
lstringa<512> copy{str_with_len_N};/1024template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } } >> А дальше уже как у всех. And then it's like everyone else.57.055.798.699.1137
lstringa<512> copy{str_with_len_N};/2048template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }65.866.5124127174
lstringa<512> copy{str_with_len_N};/4096template<typename T> void CopyDynString(benchmark::State& state) { T x(state.range(0), 'a'); for (auto _: state) { T copy{x}; benchmark::DoNotOptimize(copy); benchmark::DoNotOptimize(x); } }92.289.3182191220

# 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 Chrome 143, 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) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 10); #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); } } >> В simstr для конвертации в число достаточно куска строки, нет нужды в null терминированности. Ближайший аналог такого поведения "std::from_chars", но он к сожалению очень ограничен по возможностям. Здесь я попытался произвести тесты, близкие по логике к работе std::from_chars 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.227.131.831.5201
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); #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); } } >> from_chars требует точного указания основания счисления, не допускает знаков плюс, пробелов, префиксов 0x и т.п. from_chars requires an exact radix specification and does not allow plus signs, spaces, 0x prefixes, etc.13.512.113.311.92.16
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; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } } >> Здесь для to_int заданы такие же ограничения - проверять переполнение, десятичная система, без лидирующих пробелов и знака плюс Here, to_int has the same restrictions: check for overflow, decimal system, no leading spaces, and no plus sign.9.588.7913.416.561.4
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; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }9.548.089.6615.249.4
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; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }9.498.7413.315.249.4

# 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 Chrome 143, 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) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 16); #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); } } >> Всё то же, только для 16ричной системы Everything is the same, only for the hexadecimal system24.823.433.534.9146
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); #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); } }9.458.708.109.0057.3
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; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }7.818.5212.514.460.0
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; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }7.676.647.4313.145.9
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; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }7.718.7211.812.646.3

# 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 Chrome 143, 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) { for (auto _: state) { int res = std::strtol(s.c_str(), nullptr, 0); #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); } } >> А здесь уже парсинг произвольного числа. And here we have parsing of an arbitrary number.30.329.043.847.5208
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; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }11.314.616.522.158.9
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 if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }13.110.912.918.945.9

# 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 Chrome 143, 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) { for (auto _: state) { char* ptr = nullptr; double res = std::strtod(s.c_str(), &ptr); if (ptr == s.c_str()) { state.SkipWithError("not equal"); } #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); } }65.565.1103104578
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{}) { state.SkipWithError("not equal"); } #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); } }24.225.059.584.1273
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>(); if (!r) { state.SkipWithError("not equal"); } double res = *r; #ifdef CHECK_RESULT if (res != c) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(res); benchmark::DoNotOptimize(t); } }26.424.435.537.893.8

# 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 Chrome 143, Clang-21
std::stringstream str; ... str << "abbaabbaabbaabba";void AppendStreamConstLiteral(benchmark::State& state) { for (auto _: state) { std::string result; std::stringstream str; for (size_t c = 0; c < 64; c++) { str << TEXT_16; } result = str.str(); #ifdef CHECK_RESULT if (result.size() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(str); } }139613754726562715958
std::string str; ... str += "abbaabbaabbaabba";void AppendStdStringConstLiteral(benchmark::State& state) { for (auto _: state) { std::string result; for (size_t c = 0; c < 64; c++) { result += TEXT_16; } #ifdef CHECK_RESULT if (result.size() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); } }375350106413131434
lstringa<8> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 64; c++) { result += TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); } }3693387939421411
lstringa<128> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 64; c++) { result += TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); } } >> Чем больше внутренний буфер, тем меньше раз требуется аллокация, тем быстрее результат. The larger the internal buffer, the fewer allocations are required, and the faster the result.233245393519920
lstringa<512> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 64; c++) { result += TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); } }238217259370638
lstringa<1024> str; ... str += "abbaabbaabbaabba";template<unsigned N> void AppendLstringConstLiteral(benchmark::State& state) { for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 64; c++) { result += TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); } }163141134288509

# 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 Chrome 143, Clang-21
std::stringstream str; ... str << str_var << "abbaabbaabbaabba";void AppendStreamStrConstLiteral(benchmark::State& state) { std::string s1 = TEXT_16; for (auto _: state) { std::string result; std::stringstream s; for (size_t c = 0; c < 32; c++) { s << s1 << TEXT_16; } result = s.str(); #ifdef CHECK_RESULT if (result.size() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); } }137013704556620516329
std::string str; ... str += str_var + "abbaabbaabbaabba";void AppendStdStrStrConstLiteral(benchmark::State& state) { std::string p1 = TEXT_16; for (auto _: state) { std::string result; for (size_t c = 0; c < 32; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.size() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }13021238371238324574
lstringa<8> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }4154057168411521
lstringa<128> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }3393394445251206
lstringa<512> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }265315286391916
lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba";template<unsigned N> void AppendLstringStrConstLiteral(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }205250183286813

# 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 Chrome 143, Clang-21
std::stringstream str; ... str << str_var << "abbaabbaabbaabba"; 2048 timesvoid AppendStreamStrConstLiteralBig(benchmark::State& state) { std::string s1 = TEXT_16; for (auto _: state) { std::string result; std::stringstream s; for (size_t c = 0; c < 2048; c++) { s << s1 << TEXT_16; } result = s.str(); #ifdef CHECK_RESULT if (result.size() != 1024 * 64) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); } }123086125525217525285336833815
std::string str; ... str += str_var + "abbaabbaabbaabba"; 2048 timesvoid AppendStdStrStrConstLiteralBig(benchmark::State& state) { std::string p1 = TEXT_16; for (auto _: state) { std::string result; for (size_t c = 0; c < 2048; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.size() != 1024 * 64) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }7399773243191801192976241478
lstringa<8> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 2048; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024 * 64) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }4635149189199752566557002
lstringa<128> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 2048; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024 * 64) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }2797026787168152228256617
lstringa<512> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 2048; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024 * 64) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }1931620894162482197253906
lstringa<1024> str; ... str += str_var + "abbaabbaabbaabba"; 2048 timestemplate<unsigned N> void AppendLstringStrConstLiteralBig(benchmark::State& state) { stringa p1 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 2048; c++) { result += p1 + TEXT_16; } #ifdef CHECK_RESULT if (result.length() != 1024 * 64) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(p1); } }1564116956161222214555763

# 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 Chrome 143, Clang-21
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) { std::string result; std::stringstream s; for (size_t c = 0; c < 32; c++) { s << s1 << s2; } result = s.str(); #ifdef CHECK_RESULT if (result.size() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } }138814404414530015927
std::string str; ... str += str_var1 + str_var2;void AppendStdStr2String(benchmark::State& state) { std::string s1 = TEXT_16; std::string s2 = TEXT_16; for (auto _: state) { std::string result; for (size_t c = 0; c < 32; c++) { result += s1 + s2; } #ifdef CHECK_RESULT if (result.size() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } }14411374389439644954
lstringa<16> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += s1 + s2; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } }5004767919091852
lstringa<128> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += s1 + s2; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } }4014165236241497
lstringa<512> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += s1 + s2; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } }3703683944761196
lstringa<1024> str; ... str += str_var1 + str_var2;template<unsigned N> void AppendLstring2String(benchmark::State& state) { stra s1 = TEXT_16; stra s2 = TEXT_16; for (auto _: state) { lstringa<N> result; for (size_t c = 0; c < 32; c++) { result += s1 + s2; } #ifdef CHECK_RESULT if (result.length() != 1024) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(s1); benchmark::DoNotOptimize(s2); } }3023162883671089

# 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 Chrome 143, Clang-21
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; t << "test = " << k << " times"; std::string result = t.str(); #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } }30233250110961187925783
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"; #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } }443428106616913681
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]; std::sprintf(buf, "test = %u times", k); std::string result = buf; #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } }133714892788282310716
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); #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } }11741458184523325711
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) { T result; result.format("test = {} times", k); #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } } >> В simstr format с первого раза не помещается в такую строку без аллокации. In simstr format, the first time it doesn't fit into such a string without allocation.13481574203527308447
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) { T result; result.format("test = {} times", k); #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } } >> А в такую помещается. Используйте сразу буфера подходящего размера. And it fits in this one. Use buffers of the appropriate size right away.984109896515307294
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) { T result = "test = "_ss + k + " times"; #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } } >> Результат не помещается в SSO, возникает аллокация. The result does not fit into SSO, an allocation occurs.2863038219381418
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) { T result = "test = "_ss + k + " times"; #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } } >> А здесь и ниже - результат укладывается в SSO. Ещё раз - используйте сразу буфера подходящего размера. And here and below, the result fits within SSO. Once again, use appropriately sized buffers from the start.129148142171572
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) { T result = "test = "_ss + k + " times"; #ifdef CHECK_RESULT if (!result.starts_with("test = ") || !result.ends_with(" times")) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(k); } } } >> Под WASM размер SSO 15 символов, что явно не хватает для размещения результата, отсюда и такое время. Under WASM, the SSO size is 15 characters, which is clearly not enough to accommodate the result, hence the long time.1331371221741197

# 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 Chrome 143, Clang-21
std::string::find + substr + std::strtolvoid SplitConvertIntStdString(benchmark::State& state) { std::string numbers = NUMBER_LIST; for (auto _: state) { int total = 0; for (size_t start = 0; start < numbers.length(); ) { int delim = numbers.find("-!-", start); if (delim == std::string::npos) { delim = numbers.size(); } std::string part = numbers.substr(start, delim - start); total += std::strtol(part.c_str(), nullptr, 0); start = delim + 3; } #ifdef CHECK_RESULT if (total != 218) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(total); benchmark::DoNotOptimize(numbers); } }2592795445451443
ssa::splitter + ssa::as_intvoid SplitConvertIntSimStr(benchmark::State& state) { stra numbers = NUMBER_LIST; for (auto _: state) { int total = 0; for (auto splitter = numbers.splitter("-!-"); !splitter.is_done();) { total += splitter.next().as_int<int>(); } #ifdef CHECK_RESULT if (total != 218) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(total); benchmark::DoNotOptimize(numbers); } }157134165298595
ssa::splitf + functorvoid SplitConvertIntSplitf(benchmark::State& state) { stra numbers = NUMBER_LIST; for (auto _: state) { int total = 0; numbers.splitf<void>("-!-", [&](ssa& part){total += part.as_int<int>();}); #ifdef CHECK_RESULT if (total != 218) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(total); benchmark::DoNotOptimize(numbers); } }210139190214853

# 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 Chrome 143, Clang-21
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" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" ; std::vector<std::pair<u8s, std::string_view>> repl = { {'&', "&amp;"}, {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"} }; auto repl_all = [](std::string& str, char s, std::string_view repl) { size_t start_pos = 0; while((start_pos = str.find(s, start_pos)) != std::string::npos) { str.replace(start_pos, 1, repl); start_pos += repl.length(); } }; for (auto _: state) { std::string result{source}; for (const auto& r : repl) { repl_all(result, r.first, r.second); } #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } } >> Это наивная реализация, которая неверно отработает на таких заменах, как 'a'->'b' и 'b'->'a'. Но если замены не конфликтуют, то работает быстро. This is a naive implementation that will fail to handle substitutions such as 'a'->'b' and 'b'->'a'. But if the substitutions don't conflict, it works quickly.8811153109311914959
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" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" ; std::vector<std::pair<u8s, std::string_view>> repl = { {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"}, {'&', "&amp;"}, }; for (auto _: state) { std::string result{source}; std::string pattern; for (const auto& r : repl) { pattern += r.first; } size_t start_pos = 0; while((start_pos = result.find_first_of(pattern, start_pos)) != std::string::npos) { size_t idx = pattern.find(result[start_pos]); result.replace(start_pos, 1, repl[idx].second); start_pos += repl[idx].second.length(); } #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } } >> Дальше уже правильные реализации, не зависящие от конфликтующих замен. Further, there are correct implementations that do not depend on conflicting replacements.24802567204922099947
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" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" ; const std::string_view repl_from = "-<>'\"&"; const std::string_view repl_to[] = {"", "&lt;", "&gt;", "&#39;", "&quot;", "&amp;"}; for (auto _: state) { std::string result; for (size_t start = 0; start < source.size();) { size_t idx = source.find_first_of(repl_from, start); if (idx == std::string::npos) { result += source.substr(start); break; } if (idx > start) { result += source.substr(start, idx - start); } size_t what = repl_from.find(source[idx]); result += repl_to[what]; start = idx + 1; } #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }1093959232925984617
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 >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" ; std::vector<std::pair<u8s, ssa>> repl = { {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"}, {'&', "&amp;"}, }; for (auto _: state) { stringa result = expr_replace_symbols<u8s, UseVector>{source, repl}; #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } }12651461145415464256
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 >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" ; std::vector<std::pair<u8s, ssa>> repl = { {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"}, {'&', "&amp;"}, }; for (auto _: state) { stringa result = expr_replace_symbols<u8s, UseVector>{source, repl}; #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } }11141209125713493810
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 >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" ; for (auto _: state) { stringa result = e_repl_const_symbols<UseVector>(source, '-', "", '<', "&lt;", '>', "&gt;", '\'', "&#39;", '\"', "&quot;", '&', "&amp;" ); #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }10981207113612723231
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 >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" " ksjd-fksjd \"dkjfs-jkhdf dfj ' kdkd \"dkfdkfkdjf" ; for (auto _: state) { stringa result = e_repl_const_symbols<UseVector>(source, '-', "", '<', "&lt;", '>', "&gt;", '\'', "&#39;", '\"', "&quot;", '&', "&amp;" ); #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" " ksjdfksjd &quot;dkjfsjkhdf dfj &#39; kdkd &quot;dkfdkfkdjf" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }837854118812833050

# 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 Chrome 143, Clang-21
Short Naive (and wrong) replace symbols with std::string find + replacevoid ShortReplaceSymbolsStdStringNaiveWrong(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" ; std::vector<std::pair<u8s, std::string_view>> repl = { {'&', "&amp;"}, {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"} }; auto repl_all = [](std::string& str, char s, std::string_view repl) { size_t start_pos = 0; while((start_pos = str.find(s, start_pos)) != std::string::npos) { str.replace(start_pos, 1, repl); start_pos += repl.length(); } }; for (auto _: state) { std::string result{source}; for (const auto& r : repl) { repl_all(result, r.first, r.second); } #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } }162162307332889
Short replace symbols with std::string find_first_of + replacevoid ShortReplaceSymbolsStdStringNaiveRight(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" ; std::vector<std::pair<u8s, std::string_view>> repl = { {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"}, {'&', "&amp;"}, }; for (auto _: state) { std::string result{source}; std::string pattern; for (const auto& r : repl) { pattern += r.first; } size_t start_pos = 0; while((start_pos = result.find_first_of(pattern, start_pos)) != std::string::npos) { size_t idx = pattern.find(result[start_pos]); result.replace(start_pos, 1, repl[idx].second); start_pos += repl[idx].second.length(); } #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } }3213333614191379
Short replace symbols with std::string_view find_first_of + copyvoid ShortReplaceSymbolsStdString(benchmark::State& state) { std::string_view source = "abcdefg124 < jhsfjsh sjdfsh jfhjd && jdjdj >" ; const std::string_view repl_from = "-<>'\"&"; const std::string_view repl_to[] = {"", "&lt;", "&gt;", "&#39;", "&quot;", "&amp;"}; for (auto _: state) { std::string result; for (size_t start = 0; start < source.size();) { size_t idx = source.find_first_of(repl_from, start); if (idx == std::string::npos) { result += source.substr(start); break; } if (idx > start) { result += source.substr(start, idx - start); } size_t what = repl_from.find_first_of(source[idx]); result += repl_to[what]; start = idx + 1; } #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }159168315344804
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 >" ; std::vector<std::pair<u8s, ssa>> repl = { {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"}, {'&', "&amp;"}, }; for (auto _: state) { stringa result = expr_replace_symbols<u8s, UseVector>{source, repl}; #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } }181185242299645
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 >" ; std::vector<std::pair<u8s, ssa>> repl = { {'-', ""}, {'<', "&lt;"}, {'>', "&gt;"}, {'\'', "&#39;"}, {'\"', "&quot;"}, {'&', "&amp;"}, }; for (auto _: state) { stringa result = expr_replace_symbols<u8s, UseVector>{source, repl}; #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(repl); } }293209338380770
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 >" ; for (auto _: state) { stringa result = e_repl_const_symbols<UseVector>(source, '-', "", '<', "&lt;", '>', "&gt;", '\'', "&#39;", '\"', "&quot;", '&', "&amp;" ); #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }130147195243438
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 >" ; for (auto _: state) { stringa result = e_repl_const_symbols<UseVector>(source, '-', "", '<', "&lt;", '>', "&gt;", '\'', "&#39;", '\"', "&quot;", '&', "&amp;" ); #ifdef CHECK_RESULT if (result != "abcdefg124 &lt; jhsfjsh sjdfsh jfhjd &amp;&amp; jdjdj &gt;" ) { state.SkipWithError("not equal"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }139134309344577

# 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 Chrome 143, Clang-21
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"; std::string_view pattern = "bb"; std::string_view repl = "----"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }153159216239776
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"; std::string_view pattern = "bb"; std::string_view repl = "----"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }5535027347912406
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"; std::string_view pattern = "bb"; std::string_view repl = "----"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }1093995137214604112
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"; std::string_view pattern = "bb"; std::string_view repl = "----"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }24272262299931819118
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"; std::string_view pattern = "bb"; std::string_view repl = "----"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }598860717578784219199
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"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }129138214225620
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"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }4334756056531900
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"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }786893102810863505
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"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }16111660179520026338
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"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }306332473547379212720
replace bb to ---- by init stringa|64template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source, "bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }91.684.8168195379
replace bb to ---- by init stringa|256template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source, "bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }3092823624611126
replace bb to ---- by init stringa|512template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source, "bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }70067482410612808
replace bb to ---- by init stringa|1024template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source, "bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }15921535157821745776
replace bb to ---- by init stringa|2048template<size_t Count> void ReplaceAllLongerSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa----baaaaaaaa--------aaaaabaaaaaaaaaaaaaaaaaaaaa----a"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source, "bb", "----"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }323030003172449412197

# 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 Chrome 143, Clang-21
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"; std::string_view pattern = "bb"; std::string_view repl = "--"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }107115180193557
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"; std::string_view pattern = "bb"; std::string_view repl = "--"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }3764084685141747
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"; std::string_view pattern = "bb"; std::string_view repl = "--"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }7457028629363241
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"; std::string_view pattern = "bb"; std::string_view repl = "--"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }14811454160917276280
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"; std::string_view pattern = "bb"; std::string_view repl = "--"; std::string big_source, big_sample; for (int i = 0; i < Long; i++) { big_source += source; big_sample += sample; } for (auto _: state) { std::string result{big_source}; size_t start_pos = 0; while((start_pos = result.find(pattern, start_pos)) != std::string::npos) { result.replace(start_pos, pattern.length(), repl); start_pos += repl.length(); } #ifdef CHECK_RESULT if (result != big_sample) { state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }285527083098341712918
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"; lstringa<2048> big_source{Long, source}, big_sample{Long, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }94.592.0177186466
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"; lstringa<2048> big_source{Long, source}, big_sample{Long, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }2903024534351429
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"; lstringa<2048> big_source{Long, source}, big_sample{Long, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }5545417977832538
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"; lstringa<2048> big_source{Long, source}, big_sample{Long, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }10471033146014324898
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"; lstringa<2048> big_source{Long, source}, big_sample{Long, sample}; for (auto _: state) { lstringa<N> result = big_source; result.replace("bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); } }20562000285028089438
replace bb to -- by init stringa|64template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; ssa pattern = "bb"; ssa repl = "--"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source.to_str(), "bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }76.982.3149163318
replace bb to -- by init stringa|256template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; ssa pattern = "bb"; ssa repl = "--"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source.to_str(), "bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }238264327368958
replace bb to -- by init stringa|512template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; ssa pattern = "bb"; ssa repl = "--"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source.to_str(), "bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }4285715186341814
replace bb to -- by init stringa|1024template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; ssa pattern = "bb"; ssa repl = "--"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source.to_str(), "bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }858101297911143500
replace bb to -- by init stringa|2048template<size_t Count> void ReplaceAllEqualSimStringExpr(benchmark::State& state) { ssa source = "aaaaaaaaaaaaaaaaaaabbbaaaaaaaabbbbaaaaabaaaaaaaaaaaaaaaaaaaaabba"; ssa sample = "aaaaaaaaaaaaaaaaaaa--baaaaaaaa----aaaaabaaaaaaaaaaaaaaaaaaaaa--a"; ssa pattern = "bb"; ssa repl = "--"; lstringa<2048> big_source{Count, source}, big_sample{Count, sample}; for (auto _: state) { stringa result = e_repl(big_source.to_str(), "bb", "--"); #ifdef CHECK_RESULT if (result.to_str() != big_sample) { std::cout << result.length() << ": " << result << "\n\n" << big_sample.length() << ": " << big_sample << "\n\n"; state.SkipWithError("error in replace"); break; } #endif benchmark::DoNotOptimize(result); benchmark::DoNotOptimize(source); benchmark::DoNotOptimize(pattern); benchmark::DoNotOptimize(repl); } }16341962181221456788

# 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 Chrome 143, Clang-21
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++) { store.try_emplace(bs_sim[idx], idx); } #ifdef CHECK_RESULT if (store.size() != bs_sim.size()) { state.SkipWithError("bad inserts"); } #endif for (size_t idx = 0; idx < bs_sim.size(); idx++) { auto find = store.find(bs_sim[idx]); size_t res = find->second; #ifdef CHECK_RESULT if (res != idx) { state.SkipWithError("bad find"); } #endif benchmark::DoNotOptimize(res); } } } >> Вставляем в hashStrMapA 10000 stringa длиной от 30 до 50 символов, а потом ищем их в ней We insert 10,000 strings of length from 30 to 50 characters into hashStrMapA, and then search for them in it.36033513720383394774443965425109286
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++) { store.try_emplace(bs_std[idx], idx); } #ifdef CHECK_RESULT if (store.size() != bs_std.size()) { state.SkipWithError("bad inserts"); } #endif for (size_t idx = 0; idx < bs_std.size(); idx++) { auto find = store.find(bs_std[idx]); size_t res = find->second; #ifdef CHECK_RESULT if (res != idx) { state.SkipWithError("bad find"); } #endif benchmark::DoNotOptimize(res); } } } >> То же самое c std::string и std::unordered_map Same thing with std::string and std::unordered_map35978283743420566821756636116102064
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++) { store.emplace(bs_sim[idx], idx); } #ifdef CHECK_RESULT if (store.size() != bs_sim.size()) { state.SkipWithError("bad inserts"); } #endif for (size_t idx = 0; idx < bs_sim.size(); idx++) { ssa key = bs_sim[idx]; auto find = store.find(key); size_t res = find->second; #ifdef CHECK_RESULT if (res != idx) { state.SkipWithError("bad find"); } #endif benchmark::DoNotOptimize(res); } } } >> Теперь вставляем stringa, а ищем ssa Now we insert stringa and search for ssa36470533829722347907539273545120455
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++) { store.emplace(bs_std[idx], idx); } #ifdef CHECK_RESULT if (store.size() != bs_std.size()) { state.SkipWithError("bad inserts"); } #endif for (size_t idx = 0; idx < bs_std.size(); idx++) { std::string_view key = bs_std[idx]; auto find = store.find(std::string{key}); size_t res = find->second; #ifdef CHECK_RESULT if (res != idx) { state.SkipWithError("bad find"); } #endif benchmark::DoNotOptimize(res); } } } >> Вставляем std::string, а ищем std::string_view We insert std::string and look for std::string_view41110053934639641541164532717370000

# 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 Chrome 143, Clang-21
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; str += "("; bool add_comma = false; for (const auto& param : params) { if (add_comma) { str += ", "; } if (param.optional) { str += "["; } param.allowed_types.to_stdstr(str); if (param.optional) { str += "]"; } add_comma = true; } if (unlim_params) { if (add_comma) { str += ", "; } str += "..."; } str += ")"; //std::cout << "Len=" << str.length() << ", Cap=" << str.capacity() << "\n"; return str; } >> Обыденная задача, подобные часто могут встретится в работе: По неким данным сгенерировать текст. В этом случае по данным о неких функциях сформировать их полное имя с типами параметров и возвращаемого значения. Алгоритм на std::string. 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.674871150315825735
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 + "("; bool add_comma = false; for (const auto& param : params) { if (add_comma) { str += ", "; } if (param.optional) { str += "["; } param.allowed_types.to_stdstr(str); if (param.optional) { str += "]"; } add_comma = true; } if (unlim_params) { if (add_comma) { str += ", "; } str += "..."; } str += ")"; //std::cout << "Len=" << str.length() << ", Cap=" << str.capacity() << "\n"; return str; } >> Почти тот же алгоритм, но несколько последовательных += к строке заменены на одно += + + +. Almost the same algorithm, but several consecutive += to a string are replaced with a single += + + +.795910158516666226
Build func full name std::stream;std::string build_full_name_stream() const { std::ostringstream str; if (has_ret_type_resolver) { str << "any"; } else { str << type_names_sv[(unsigned)ret_type]; } str << " " << std_name << "("; bool add_comma = false; for (const auto& param : params) { if (add_comma) { str << ", "; } if (param.optional) { str << "["; } param.allowed_types.to_stream(str); if (param.optional) { str << "]"; } add_comma = true; } if (unlim_params) { if (add_comma) { str << ", "; } str << "..."; } str << ")"; return str.str(); } >> Строим имя функции через std::ostringstream и << We construct the function name through std::ostringstream and <<257426338326970625795
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; for (const auto& param : params) { str += e_if(add_comma, ", ") + e_if(param.optional, "["); param.allowed_types.to_simstr(str); if (param.optional) { str += "]"; } add_comma = true; } return str + e_if(unlim_params, e_if(add_comma, ", ") + "...") + ")"; } >> Реализация на simstr строках и строковых выражениях. Инфа о параметрах добавляется в текущую строку Implementation using simstr strings and string expressions. Parameter information is appended to the current line.4854517608712962
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; for (const auto& param : params) { str += e_if(add_comma, ", ") + e_if(param.optional, "[") + param.allowed_types.get_simstr() + e_if(param.optional, "]"); add_comma = true; } return str + e_if(unlim_params, e_if(add_comma, ", ") + "...") + ")"; } >> Реализация на simstr строках и строковых выражениях. Инфа о параметрах добавляется во временную строку, а потом разом добавляется в текущую строку. Позволяет операции в цикле записать в одну строку, но чуть проигрывает по времени выполнения. Implementation using simstr strings and string expressions. Parameter information is added to a temporary string, and then all at once to the current string. This allows loop operations to be written in a single string, but is slightly slower in execution time.6086568649563450

# Make Upper

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 Chrome 143, Clang-21
To upper case std::wstringvoid UpperCaseStd(benchmark::State& state) { static const auto& loc = std::locale("en_US.utf8"); for (auto _: state) { std::wstring test = L"TestПриветTest"; benchmark::DoNotOptimize(test); std::transform(test.begin(), test.end(), test.begin(), [](wchar_t s) { return std::toupper(s, loc); }); benchmark::DoNotOptimize(test); #ifdef CHECK_RESULT if (test != L"TESTПРИВЕТTEST") { state.SkipWithError("Bad upper case"); } #endif } }151165152214521276
To upper case lstringw<15>void UpperCaseSim(benchmark::State& state) { for (auto _: state) { lstringw<15> test = L"TestПриветTest"; benchmark::DoNotOptimize(test); test.upper(); benchmark::DoNotOptimize(test); #ifdef CHECK_RESULT if (test != L"TESTПРИВЕТTEST") { state.SkipWithError("Bad upper case"); } #endif } }42.745.138.344.5132