Skip to content

Commit d4376a4

Browse files
committed
[libc++][format][1/7] Adds more benchmarks.
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 2fc71e4 commit d4376a4

File tree

4 files changed

+435
-0
lines changed

4 files changed

+435
-0
lines changed

libcxx/test/benchmarks/CMakeLists.txt

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

0 commit comments

Comments
 (0)