Skip to content

Commit d54b1cf

Browse files
authored
[libc++][format][1/3] Adds more benchmarks. (#101803)
This patch is the start of a series to improve the speed of std::format, std::format_to, std::format_to_n, and std::formatted_size. This is mostly achieved by changing the __output_buffer class. This new __output_buffer class also makes it easier to implement buffering for P3107R5 "Permit an efficient implementation of std::print"
1 parent 8326fb2 commit d54b1cf

File tree

5 files changed

+462
-2
lines changed

5 files changed

+462
-2
lines changed

libcxx/test/benchmarks/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ set(BENCHMARK_TESTS
147147
deque_iterator.bench.cpp
148148
exception_ptr.bench.cpp
149149
filesystem.bench.cpp
150+
format/write_double_comparison.bench.cpp
151+
format/write_int_comparison.bench.cpp
152+
format/write_string_comparison.bench.cpp
150153
format_to_n.bench.cpp
151154
format_to.bench.cpp
152155
format.bench.cpp

libcxx/test/benchmarks/format.bench.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ static void BM_format_string(benchmark::State& state) {
2020
size_t size = state.range(0);
2121
std::basic_string<CharT> str(size, CharT('*'));
2222

23-
while (state.KeepRunningBatch(str.size()))
24-
benchmark::DoNotOptimize(std::format(CSTR("{}"), str));
23+
while (state.KeepRunningBatch(str.size())) {
24+
std::basic_string<CharT> s = std::format(CSTR("{}"), str);
25+
benchmark::DoNotOptimize(s);
26+
}
2527

2628
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
2729
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <array>
10+
#include <charconv>
11+
#include <cstdio>
12+
#include <format>
13+
#include <iterator>
14+
#include <list>
15+
#include <random>
16+
#include <vector>
17+
18+
#include "benchmark/benchmark.h"
19+
20+
std::array data = [] {
21+
std::uniform_real_distribution<double> distribution;
22+
std::mt19937 generator;
23+
std::array<double, 1000> result;
24+
std::generate_n(result.begin(), result.size(), [&] { return distribution(generator); });
25+
return result;
26+
}();
27+
28+
static void BM_sprintf(benchmark::State& state) {
29+
std::array<char, 100> output;
30+
while (state.KeepRunningBatch(data.size()))
31+
for (auto value : data) {
32+
sprintf(output.data(), "%f", value);
33+
benchmark::DoNotOptimize(output.data());
34+
}
35+
}
36+
37+
static void BM_to_string(benchmark::State& state) {
38+
while (state.KeepRunningBatch(data.size()))
39+
for (auto value : data) {
40+
std::string s = std::to_string(value);
41+
benchmark::DoNotOptimize(s);
42+
}
43+
}
44+
45+
static void BM_to_chars(benchmark::State& state) {
46+
std::array<char, 100> output;
47+
48+
while (state.KeepRunningBatch(data.size()))
49+
for (auto value : data) {
50+
std::to_chars(output.data(), output.data() + output.size(), value);
51+
benchmark::DoNotOptimize(output.data());
52+
}
53+
}
54+
55+
static void BM_to_chars_as_string(benchmark::State& state) {
56+
std::array<char, 100> output;
57+
58+
while (state.KeepRunningBatch(data.size()))
59+
for (auto value : data) {
60+
char* end = std::to_chars(output.data(), output.data() + output.size(), value).ptr;
61+
std::string s{output.data(), end};
62+
benchmark::DoNotOptimize(s);
63+
}
64+
}
65+
66+
static void BM_format(benchmark::State& state) {
67+
while (state.KeepRunningBatch(data.size()))
68+
for (auto value : data) {
69+
std::string s = std::format("{}", value);
70+
benchmark::DoNotOptimize(s);
71+
}
72+
}
73+
74+
template <class C>
75+
static void BM_format_to_back_inserter(benchmark::State& state) {
76+
while (state.KeepRunningBatch(data.size()))
77+
for (auto value : data) {
78+
C c;
79+
std::format_to(std::back_inserter(c), "{}", value);
80+
benchmark::DoNotOptimize(c);
81+
}
82+
}
83+
84+
template <class F>
85+
static void BM_format_to_iterator(benchmark::State& state, F&& f) {
86+
auto output = f();
87+
while (state.KeepRunningBatch(data.size()))
88+
for (auto value : data) {
89+
std::format_to(std::begin(output), "{}", value);
90+
benchmark::DoNotOptimize(std::begin(output));
91+
}
92+
}
93+
94+
BENCHMARK(BM_sprintf);
95+
BENCHMARK(BM_to_string);
96+
BENCHMARK(BM_to_chars);
97+
BENCHMARK(BM_to_chars_as_string);
98+
BENCHMARK(BM_format);
99+
BENCHMARK_TEMPLATE(BM_format_to_back_inserter, std::string);
100+
BENCHMARK_TEMPLATE(BM_format_to_back_inserter, std::vector<char>);
101+
BENCHMARK_TEMPLATE(BM_format_to_back_inserter, std::list<char>);
102+
BENCHMARK_CAPTURE(BM_format_to_iterator, <std::array>, ([] {
103+
std::array<char, 100> a;
104+
return a;
105+
}));
106+
BENCHMARK_CAPTURE(BM_format_to_iterator, <std::string>, ([] {
107+
std::string s;
108+
s.resize(100);
109+
return s;
110+
}));
111+
BENCHMARK_CAPTURE(BM_format_to_iterator, <std::vector>, ([] {
112+
std::vector<char> v;
113+
v.resize(100);
114+
return v;
115+
}));
116+
117+
BENCHMARK_MAIN();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include <array>
10+
#include <charconv>
11+
#include <cstdio>
12+
#include <format>
13+
#include <iterator>
14+
#include <list>
15+
#include <random>
16+
#include <vector>
17+
18+
#include "benchmark/benchmark.h"
19+
20+
std::array data = [] {
21+
std::uniform_int_distribution<int> distribution{std::numeric_limits<int>::min(), std::numeric_limits<int>::max()};
22+
std::mt19937 generator;
23+
std::array<int, 1000> result;
24+
std::generate_n(result.begin(), result.size(), [&] { return distribution(generator); });
25+
return result;
26+
}();
27+
28+
static void BM_sprintf(benchmark::State& state) {
29+
std::array<char, 100> output;
30+
while (state.KeepRunningBatch(data.size()))
31+
for (auto value : data) {
32+
sprintf(output.data(), "%d", value);
33+
benchmark::DoNotOptimize(output.data());
34+
}
35+
}
36+
37+
static void BM_to_string(benchmark::State& state) {
38+
while (state.KeepRunningBatch(data.size()))
39+
for (auto value : data) {
40+
std::string s = std::to_string(value);
41+
benchmark::DoNotOptimize(s);
42+
}
43+
}
44+
45+
static void BM_to_chars(benchmark::State& state) {
46+
std::array<char, 100> output;
47+
48+
while (state.KeepRunningBatch(data.size()))
49+
for (auto value : data) {
50+
std::to_chars(output.data(), output.data() + output.size(), value);
51+
benchmark::DoNotOptimize(output.data());
52+
}
53+
}
54+
55+
static void BM_to_chars_as_string(benchmark::State& state) {
56+
std::array<char, 100> output;
57+
58+
while (state.KeepRunningBatch(data.size()))
59+
for (auto value : data) {
60+
char* end = std::to_chars(output.data(), output.data() + output.size(), value).ptr;
61+
std::string s{output.data(), end};
62+
benchmark::DoNotOptimize(s);
63+
}
64+
}
65+
66+
static void BM_format(benchmark::State& state) {
67+
while (state.KeepRunningBatch(data.size()))
68+
for (auto value : data) {
69+
std::string s = std::format("{}", value);
70+
benchmark::DoNotOptimize(s);
71+
}
72+
}
73+
74+
template <class C>
75+
static void BM_format_to_back_inserter(benchmark::State& state) {
76+
while (state.KeepRunningBatch(data.size()))
77+
for (auto value : data) {
78+
C c;
79+
std::format_to(std::back_inserter(c), "{}", value);
80+
benchmark::DoNotOptimize(c);
81+
}
82+
}
83+
84+
template <class F>
85+
static void BM_format_to_iterator(benchmark::State& state, F&& f) {
86+
auto output = f();
87+
while (state.KeepRunningBatch(data.size()))
88+
for (auto value : data) {
89+
std::format_to(std::begin(output), "{}", value);
90+
benchmark::DoNotOptimize(std::begin(output));
91+
}
92+
}
93+
94+
BENCHMARK(BM_sprintf);
95+
BENCHMARK(BM_to_string);
96+
BENCHMARK(BM_to_chars);
97+
BENCHMARK(BM_to_chars_as_string);
98+
BENCHMARK(BM_format);
99+
BENCHMARK_TEMPLATE(BM_format_to_back_inserter, std::string);
100+
BENCHMARK_TEMPLATE(BM_format_to_back_inserter, std::vector<char>);
101+
BENCHMARK_TEMPLATE(BM_format_to_back_inserter, std::list<char>);
102+
BENCHMARK_CAPTURE(BM_format_to_iterator, <std::array>, ([] {
103+
std::array<char, 100> a;
104+
return a;
105+
}));
106+
BENCHMARK_CAPTURE(BM_format_to_iterator, <std::string>, ([] {
107+
std::string s;
108+
s.resize(100);
109+
return s;
110+
}));
111+
BENCHMARK_CAPTURE(BM_format_to_iterator, <std::vector>, ([] {
112+
std::vector<char> v;
113+
v.resize(100);
114+
return v;
115+
}));
116+
117+
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)