Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++][format] Adds print benchmarks. #129765

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

mordante
Copy link
Member

@mordante mordante commented Mar 4, 2025

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.)

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.)
@mordante mordante requested a review from a team as a code owner March 4, 2025 20:04
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Mar 4, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 4, 2025

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

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&lt;char&gt;, which is not a stack buffer. However there is not a good Standard type. (std::inplace_vector would be a better type.)


Full diff: https://github.com/llvm/llvm-project/pull/129765.diff

1 Files Affected:

  • (added) libcxx/test/benchmarks/print.bench.cpp (+79)
diff --git a/libcxx/test/benchmarks/print.bench.cpp b/libcxx/test/benchmarks/print.bench.cpp
new file mode 100644
index 0000000000000..feed14138b9d9
--- /dev/null
+++ b/libcxx/test/benchmarks/print.bench.cpp
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++23
+
+// This benchmark writes the print and benchmark data to stdout. In order to
+// preserve the benchmark output it needs to be stored in a file (using the
+// console format). Another issue with the benchmark is the time it takes to
+// write output to the real terminal. In order to avoid that overhead write the
+// output to a fast "terminal", like /dev/null. For example, the printf
+//   console    1546   ns
+//   /dev/null    70.9 ns
+// An example of a good test invocation.
+// BENCHMARK_OUT=benchmark.txt BENCHMARK_OUT_FORMAT=console <exe> >/dev/null
+
+#include <print>
+
+#include <cstdio>
+#include <string>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+
+void printf(benchmark::State& s) {
+  while (s.KeepRunning())
+    std::printf("The answer to life, the universe, and everything is %d.\n", 42);
+}
+BENCHMARK(printf);
+
+void vprint_string(std::string_view fmt, std::format_args args) {
+  auto s             = std::vformat(fmt, args);
+  std::size_t result = fwrite(s.data(), 1, s.size(), stdout);
+  if (result < s.size())
+    throw std::format_error("fwrite error");
+}
+
+template <typename... T>
+void print_string(std::format_string<T...> fmt, T&&... args) {
+  vprint_string(fmt.get(), std::make_format_args(args...));
+}
+
+void print_string(benchmark::State& s) {
+  while (s.KeepRunning()) {
+    print_string("The answer to life, the universe, and everything is {}.\n", 42);
+  }
+}
+BENCHMARK(print_string);
+
+void vprint_stack(std::string_view fmt, std::format_args args) {
+  auto buf = std::vector<char>{};
+  std::vformat_to(std::back_inserter(buf), fmt, args);
+  std::size_t result = fwrite(buf.data(), 1, buf.size(), stdout);
+  if (result < buf.size())
+    throw std::format_error("fwrite error");
+}
+
+template <typename... T>
+void print_stack(std::format_string<T...> fmt, T&&... args) {
+  vprint_stack(fmt.get(), std::make_format_args(args...));
+}
+
+void print_stack(benchmark::State& s) {
+  while (s.KeepRunning()) {
+    print_stack("The answer to life, the universe, and everything is {}.\n", 42);
+  }
+}
+BENCHMARK(print_stack);
+
+void print_direct(benchmark::State& s) {
+  while (s.KeepRunning())
+    std::print("The answer to life, the universe, and everything is {}.\n", 42);
+}
+BENCHMARK(print_direct);
+
+BENCHMARK_MAIN();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants