[libcxx-commits] [libcxx] [libc++] Add benchmark for `std::exception_ptr` (PR #164278)

Adrian Vogelsgesang via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 21 03:53:07 PDT 2025


https://github.com/vogelsgesang updated https://github.com/llvm/llvm-project/pull/164278

>From 47823b92f0e160893e34b339c92e1c455d69cbea Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Mon, 20 Oct 2025 13:47:44 +0000
Subject: [PATCH 1/4] [libc++] Add benchmark for `std::exception_ptr`

This commit adds benchmarks for `std::exception_ptr` to set a baseline
in preparation for follow-up optimizations.
---
 .../test/benchmarks/exception_ptr.bench.cpp   | 45 +++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/libcxx/test/benchmarks/exception_ptr.bench.cpp b/libcxx/test/benchmarks/exception_ptr.bench.cpp
index 7791c510b1eb6..1ff1d8b10d2b0 100644
--- a/libcxx/test/benchmarks/exception_ptr.bench.cpp
+++ b/libcxx/test/benchmarks/exception_ptr.bench.cpp
@@ -18,4 +18,49 @@ void bm_make_exception_ptr(benchmark::State& state) {
 }
 BENCHMARK(bm_make_exception_ptr)->ThreadRange(1, 8);
 
+static bool exception_ptr_moves_copies_swap(std::exception_ptr p1) {
+  // Taken from https://github.com/llvm/llvm-project/issues/44892
+  std::exception_ptr p2(p1);            // Copy constructor
+  std::exception_ptr p3(std::move(p2)); // Move constructor
+  p2 = std::move(p1);                   // Move assignment
+  p1 = p2;                              // Copy assignment
+  swap(p1, p2);                         // Swap
+  // Comparisons against nullptr. The overhead from creating temporary `exception_ptr`
+  // instances should be optimized out.
+  bool is_null  = p1 == nullptr && nullptr == p2;
+  bool is_equal = p1 == p2; // Comparison
+  return is_null && is_equal;
+}
+
+void bm_nonnull_exception_ptr(benchmark::State& state) {
+  std::exception_ptr excptr = std::make_exception_ptr(42);
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(excptr);
+    benchmark::DoNotOptimize(exception_ptr_moves_copies_swap(excptr));
+  }
+}
+BENCHMARK(bm_nonnull_exception_ptr);
+
+void bm_null_exception_ptr(benchmark::State& state) {
+  std::exception_ptr excptr;
+  for (auto _ : state) {
+    // All of the `exception_ptr_noops` are no-ops but the optimizer
+    // cannot optimize them away, because the `DoNotOptimize` calls
+    // prevent the optimizer from doing so.
+    benchmark::DoNotOptimize(excptr);
+    benchmark::DoNotOptimize(exception_ptr_moves_copies_swap(excptr));
+  }
+}
+BENCHMARK(bm_null_exception_ptr);
+
+void bm_optimized_null_exception_ptr(benchmark::State& state) {
+  for (auto _ : state) {
+    // All of the `exception_ptr_noops` are no-ops because
+    // the exception_ptr is empty. Hence, the compiler should
+    // be able to optimize them very aggressively.
+    benchmark::DoNotOptimize(exception_ptr_moves_copies_swap(std::exception_ptr{nullptr}));
+  }
+}
+BENCHMARK(bm_optimized_null_exception_ptr);
+
 BENCHMARK_MAIN();

>From 2da884557c493cdc10ea5c34cce92bffad78b9f1 Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Mon, 20 Oct 2025 21:11:04 +0000
Subject: [PATCH 2/4] Update comments

---
 libcxx/test/benchmarks/exception_ptr.bench.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/benchmarks/exception_ptr.bench.cpp b/libcxx/test/benchmarks/exception_ptr.bench.cpp
index 1ff1d8b10d2b0..467deeb3fd96d 100644
--- a/libcxx/test/benchmarks/exception_ptr.bench.cpp
+++ b/libcxx/test/benchmarks/exception_ptr.bench.cpp
@@ -32,6 +32,7 @@ static bool exception_ptr_moves_copies_swap(std::exception_ptr p1) {
   return is_null && is_equal;
 }
 
+// Benchmark copies, moves and comparisons of a non-null exception_ptr.
 void bm_nonnull_exception_ptr(benchmark::State& state) {
   std::exception_ptr excptr = std::make_exception_ptr(42);
   for (auto _ : state) {
@@ -41,23 +42,22 @@ void bm_nonnull_exception_ptr(benchmark::State& state) {
 }
 BENCHMARK(bm_nonnull_exception_ptr);
 
+// Benchmark copies, moves and comparisons of a nullptr exception_ptr
+// where the compiler cannot prove that the exception_ptr is always
+// a nullptr and needs to emit runtime checks.
 void bm_null_exception_ptr(benchmark::State& state) {
   std::exception_ptr excptr;
   for (auto _ : state) {
-    // All of the `exception_ptr_noops` are no-ops but the optimizer
-    // cannot optimize them away, because the `DoNotOptimize` calls
-    // prevent the optimizer from doing so.
     benchmark::DoNotOptimize(excptr);
     benchmark::DoNotOptimize(exception_ptr_moves_copies_swap(excptr));
   }
 }
 BENCHMARK(bm_null_exception_ptr);
 
+// Benchmark copies, moves and comparisons of a nullptr exception_ptr
+// where the compiler can proof that the exception_ptr is always a nullptr.
 void bm_optimized_null_exception_ptr(benchmark::State& state) {
   for (auto _ : state) {
-    // All of the `exception_ptr_noops` are no-ops because
-    // the exception_ptr is empty. Hence, the compiler should
-    // be able to optimize them very aggressively.
     benchmark::DoNotOptimize(exception_ptr_moves_copies_swap(std::exception_ptr{nullptr}));
   }
 }

>From bb6480e8de53232fee727053b5f9955df67af3fd Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <adrian.vogelsgesang at tum.de>
Date: Tue, 21 Oct 2025 11:59:33 +0200
Subject: [PATCH 3/4] update link in comment

Co-authored-by: Nikolas Klauser <nikolasklauser at berlin.de>
---
 libcxx/test/benchmarks/exception_ptr.bench.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/benchmarks/exception_ptr.bench.cpp b/libcxx/test/benchmarks/exception_ptr.bench.cpp
index 467deeb3fd96d..fe754898f0c96 100644
--- a/libcxx/test/benchmarks/exception_ptr.bench.cpp
+++ b/libcxx/test/benchmarks/exception_ptr.bench.cpp
@@ -19,7 +19,7 @@ void bm_make_exception_ptr(benchmark::State& state) {
 BENCHMARK(bm_make_exception_ptr)->ThreadRange(1, 8);
 
 static bool exception_ptr_moves_copies_swap(std::exception_ptr p1) {
-  // Taken from https://github.com/llvm/llvm-project/issues/44892
+  // Taken from https://llvm.org/PR45547
   std::exception_ptr p2(p1);            // Copy constructor
   std::exception_ptr p3(std::move(p2)); // Move constructor
   p2 = std::move(p1);                   // Move assignment

>From a799f0e92534d254ce1bca431c43acf2bfb4f23c Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Tue, 21 Oct 2025 10:52:47 +0000
Subject: [PATCH 4/4] Remove some comments

---
 libcxx/test/benchmarks/exception_ptr.bench.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libcxx/test/benchmarks/exception_ptr.bench.cpp b/libcxx/test/benchmarks/exception_ptr.bench.cpp
index fe754898f0c96..c3a3aa3e044c9 100644
--- a/libcxx/test/benchmarks/exception_ptr.bench.cpp
+++ b/libcxx/test/benchmarks/exception_ptr.bench.cpp
@@ -20,15 +20,15 @@ BENCHMARK(bm_make_exception_ptr)->ThreadRange(1, 8);
 
 static bool exception_ptr_moves_copies_swap(std::exception_ptr p1) {
   // Taken from https://llvm.org/PR45547
-  std::exception_ptr p2(p1);            // Copy constructor
-  std::exception_ptr p3(std::move(p2)); // Move constructor
-  p2 = std::move(p1);                   // Move assignment
-  p1 = p2;                              // Copy assignment
-  swap(p1, p2);                         // Swap
+  std::exception_ptr p2(p1);
+  std::exception_ptr p3(std::move(p2));
+  p2 = std::move(p1);
+  p1 = p2;
+  swap(p1, p2);
   // Comparisons against nullptr. The overhead from creating temporary `exception_ptr`
   // instances should be optimized out.
   bool is_null  = p1 == nullptr && nullptr == p2;
-  bool is_equal = p1 == p2; // Comparison
+  bool is_equal = p1 == p2;
   return is_null && is_equal;
 }
 



More information about the libcxx-commits mailing list