Skip to content

Commit 97732a4

Browse files
committed
[libc++][format] Adds print benchmarks.
P3107R5 "Permit an efficient implementation of std::print" should improve the performance of std::print. Before implementing these improvements it adds the benchmark provided in the paper. It replaces the `fmt::memory_buffer` with `std::vector<char>`, which is not a stack buffer. However there is not a good Standard type. (std::inplace_vector would be a better type.)
1 parent f9a6ea4 commit 97732a4

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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+
// REQUIRES: std-at-least-c++23
9+
10+
// This benchmark writes the print and benchmark data to stdout. In order to
11+
// preserve the benchmark output it needs to be stored in a file (using the
12+
// console format). Another issue with the benchmark is the time it takes to
13+
// write output to the real terminal. In order to avoid that overhead write the
14+
// output to a fast "terminal", like /dev/null. For example, the printf
15+
// console 1546 ns
16+
// /dev/null 70.9 ns
17+
// An example of a good test invocation.
18+
// BENCHMARK_OUT=benchmark.txt BENCHMARK_OUT_FORMAT=console <exe> >/dev/null
19+
20+
#include <print>
21+
22+
#include <cstdio>
23+
#include <string>
24+
#include <vector>
25+
26+
#include "benchmark/benchmark.h"
27+
28+
void printf(benchmark::State& s) {
29+
while (s.KeepRunning())
30+
std::printf("The answer to life, the universe, and everything is %d.\n", 42);
31+
}
32+
BENCHMARK(printf);
33+
34+
void vprint_string(std::string_view fmt, std::format_args args) {
35+
auto s = std::vformat(fmt, args);
36+
std::size_t result = fwrite(s.data(), 1, s.size(), stdout);
37+
if (result < s.size())
38+
throw std::format_error("fwrite error");
39+
}
40+
41+
template <typename... T>
42+
void print_string(std::format_string<T...> fmt, T&&... args) {
43+
vprint_string(fmt.get(), std::make_format_args(args...));
44+
}
45+
46+
void print_string(benchmark::State& s) {
47+
while (s.KeepRunning()) {
48+
print_string("The answer to life, the universe, and everything is {}.\n", 42);
49+
}
50+
}
51+
BENCHMARK(print_string);
52+
53+
void vprint_stack(std::string_view fmt, std::format_args args) {
54+
auto buf = std::vector<char>{};
55+
std::vformat_to(std::back_inserter(buf), fmt, args);
56+
std::size_t result = fwrite(buf.data(), 1, buf.size(), stdout);
57+
if (result < buf.size())
58+
throw std::format_error("fwrite error");
59+
}
60+
61+
template <typename... T>
62+
void print_stack(std::format_string<T...> fmt, T&&... args) {
63+
vprint_stack(fmt.get(), std::make_format_args(args...));
64+
}
65+
66+
void print_stack(benchmark::State& s) {
67+
while (s.KeepRunning()) {
68+
print_stack("The answer to life, the universe, and everything is {}.\n", 42);
69+
}
70+
}
71+
BENCHMARK(print_stack);
72+
73+
void print_direct(benchmark::State& s) {
74+
while (s.KeepRunning())
75+
std::print("The answer to life, the universe, and everything is {}.\n", 42);
76+
}
77+
BENCHMARK(print_direct);
78+
79+
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)