[libcxx-commits] [libcxx] [libc++] Add benchmarks for throw/catch (PR #231000)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Oct 20 08:46:39 PDT 2026
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/231000
>From 657e07570cd46f264cf29ad76250c04c922eb431 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Sun, 11 Oct 2026 17:51:47 +0200
Subject: [PATCH] [libc++] Add benchmarks for throw/catch
---
.../libcxxabi/throw_catch.bench.cpp | 113 ++++++++++++++++++
1 file changed, 113 insertions(+)
create mode 100644 libcxx/test/benchmarks/libcxxabi/throw_catch.bench.cpp
diff --git a/libcxx/test/benchmarks/libcxxabi/throw_catch.bench.cpp b/libcxx/test/benchmarks/libcxxabi/throw_catch.bench.cpp
new file mode 100644
index 00000000000000..e9367ad856864f
--- /dev/null
+++ b/libcxx/test/benchmarks/libcxxabi/throw_catch.bench.cpp
@@ -0,0 +1,113 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+#include <cstddef>
+
+#include "benchmark/benchmark.h"
+#include "test_macros.h"
+
+template <std::size_t Depth>
+struct Chain : Chain<Depth - 1> {};
+
+template <>
+struct Chain<0> {
+ Chain() = default;
+ Chain(const Chain&) = default;
+ Chain& operator=(const Chain&) = default;
+ virtual ~Chain() noexcept = default;
+};
+
+template <std::size_t Index, std::size_t Depth>
+struct Dag : Dag<Index, Depth - 1>, Dag<Index + 1, Depth - 1> {};
+
+template <std::size_t Index>
+struct Dag<Index, 0> {
+ Dag() = default;
+ Dag(const Dag&) = default;
+ Dag& operator=(const Dag&) = default;
+ virtual ~Dag() noexcept = default;
+};
+
+template <std::size_t Depth>
+struct VChain : virtual VChain<Depth - 1> {};
+
+template <>
+struct VChain<0> {
+ VChain() = default;
+ VChain(const VChain&) = default;
+ VChain& operator=(const VChain&) = default;
+ virtual ~VChain() noexcept = default;
+};
+
+template <std::size_t Index, std::size_t Depth>
+struct VDag : virtual VDag<Index, Depth - 1>, virtual VDag<Index + 1, Depth - 1> {};
+
+template <std::size_t Index>
+struct VDag<Index, 0> {
+ VDag() = default;
+ VDag(const VDag&) = default;
+ VDag& operator=(const VDag&) = default;
+ virtual ~VDag() noexcept = default;
+};
+
+template <class ThrowT, class CatchT>
+static TEST_ALIGN_BENCHMARK void ThrowCatch(benchmark::State& state) {
+ for (auto _ : state) {
+ try {
+ throw ThrowT();
+ } catch (CatchT& v) {
+ benchmark::DoNotOptimize(v);
+ }
+ }
+}
+
+// Downcast along a chain from base to the most derived type
+BENCHMARK(ThrowCatch<Chain<1>, Chain<0>>)->Name("throw/catch (Chain, 1 level)");
+BENCHMARK(ThrowCatch<Chain<2>, Chain<0>>)->Name("throw/catch (Chain, 2 levels)");
+BENCHMARK(ThrowCatch<Chain<3>, Chain<0>>)->Name("throw/catch (Chain, 3 levels)");
+BENCHMARK(ThrowCatch<Chain<9>, Chain<0>>)->Name("throw/catch (Chain, 9 levels)");
+
+// Downcast along a virtual inheritance chain from base to the most derived type
+BENCHMARK(ThrowCatch<VChain<1>, VChain<0>>)->Name("throw/catch (VChain, 1 level)");
+BENCHMARK(ThrowCatch<VChain<2>, VChain<0>>)->Name("throw/catch (VChain, 2 levels)");
+BENCHMARK(ThrowCatch<VChain<5>, VChain<0>>)->Name("throw/catch (VChain, 5 levels)");
+
+// Downcast along a DAG from base to the most derived type
+BENCHMARK(ThrowCatch<Dag<0, 5>, Dag<5, 0>>)->Name("throw/catch (DAG rightmost, 5 levels)");
+BENCHMARK(ThrowCatch<Dag<0, 5>, Dag<0, 0>>)->Name("throw/catch (DAG leftmost, 5 levels)");
+
+// Downcast along a virtual inheritance DAG from base to the most derived type
+BENCHMARK(ThrowCatch<VDag<0, 5>, VDag<5, 0>>)->Name("throw/catch (VDAG rightmost, 5 levels)");
+BENCHMARK(ThrowCatch<VDag<0, 5>, VDag<0, 0>>)->Name("throw/catch (VDAG leftmost, 5 levels)");
+
+[[gnu::noinline, noreturn]] void throw_exception() { throw std::exception(); }
+[[gnu::noinline, noreturn]] void in_between_func() {
+ int i;
+ struct S {
+ S(int* i) : i(i) {}
+ int* i;
+ [[gnu::noinline]] ~S() {
+ *i = 0;
+ }
+ } s(&i);
+
+ throw_exception();
+}
+
+static void multi_level_throw(benchmark::State& state) {
+ for (auto _ : state) {
+ try {
+ in_between_func();
+ } catch (const std::exception&) {
+ }
+ }
+}
+
+BENCHMARK(multi_level_throw);
More information about the libcxx-commits
mailing list