Skip to content

Instantly share code, notes, and snippets.

@Lancern
Last active November 4, 2022 03:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lancern/212a26a3144343f459428dffe202cde0 to your computer and use it in GitHub Desktop.
Save Lancern/212a26a3144343f459428dffe202cde0 to your computer and use it in GitHub Desktop.
dynamic_cast performance benchmark suite and results
#include <cstddef>
#include "benchmark/benchmark.h"
template <std::size_t Depth>
struct Chain : Chain<Depth - 1> {};
template <>
struct Chain<0> {
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> {
virtual ~Dag() noexcept = default;
};
template <std::size_t Depth>
struct VChain : virtual VChain<Depth - 1> {};
template <>
struct VChain<0> {
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> {
virtual ~VDag() noexcept = default;
};
template <typename Dyn, typename From, typename To = Dyn>
static void DynCast(benchmark::State& state) {
Dyn obj;
From* from_ptr = &obj;
for (auto _ : state) {
To* to_ptr = dynamic_cast<To*>(from_ptr);
benchmark::DoNotOptimize(to_ptr);
}
}
static void StaticCast(benchmark::State& state) {
Chain<9> obj;
Chain<0>* from_ptr = &obj;
for (auto _ : state) {
Chain<9>* to_ptr = static_cast<Chain<9>*>(from_ptr);
benchmark::DoNotOptimize(to_ptr);
}
}
// Downcast along a chain from base to the most derived type
BENCHMARK(DynCast<Chain<1>, Chain<0>>)->Name("Chain, 1 level");
BENCHMARK(DynCast<Chain<2>, Chain<0>>)->Name("Chain, 2 levels");
BENCHMARK(DynCast<Chain<3>, Chain<0>>)->Name("Chain, 3 levels");
BENCHMARK(DynCast<Chain<4>, Chain<0>>)->Name("Chain, 4 levels");
BENCHMARK(DynCast<Chain<5>, Chain<0>>)->Name("Chain, 5 levels");
BENCHMARK(DynCast<Chain<6>, Chain<0>>)->Name("Chain, 6 levels");
BENCHMARK(DynCast<Chain<7>, Chain<0>>)->Name("Chain, 7 levels");
BENCHMARK(DynCast<Chain<8>, Chain<0>>)->Name("Chain, 8 levels");
BENCHMARK(DynCast<Chain<9>, Chain<0>>)->Name("Chain, 9 levels");
// Downcast along a chain from base to the middle of the chain
BENCHMARK(DynCast<Chain<2>, Chain<0>, Chain<1>>)->Name("Chain middle, 1 level");
BENCHMARK(DynCast<Chain<4>, Chain<0>, Chain<2>>)->Name("Chain middle, 2 levels");
BENCHMARK(DynCast<Chain<6>, Chain<0>, Chain<3>>)->Name("Chain middle, 3 levels");
BENCHMARK(DynCast<Chain<8>, Chain<0>, Chain<4>>)->Name("Chain middle, 4 levels");
// Downcast along a chain that fails
BENCHMARK(DynCast<Chain<1>, Chain<0>, Chain<9>>)->Name("Chain fail, 1 level");
BENCHMARK(DynCast<Chain<2>, Chain<0>, Chain<9>>)->Name("Chain fail, 2 levels");
BENCHMARK(DynCast<Chain<3>, Chain<0>, Chain<9>>)->Name("Chain fail, 3 levels");
BENCHMARK(DynCast<Chain<4>, Chain<0>, Chain<9>>)->Name("Chain fail, 4 levels");
BENCHMARK(DynCast<Chain<5>, Chain<0>, Chain<9>>)->Name("Chain fail, 5 levels");
BENCHMARK(DynCast<Chain<6>, Chain<0>, Chain<9>>)->Name("Chain fail, 6 levels");
BENCHMARK(DynCast<Chain<7>, Chain<0>, Chain<9>>)->Name("Chain fail, 7 levels");
BENCHMARK(DynCast<Chain<8>, Chain<0>, Chain<9>>)->Name("Chain fail, 8 levels");
// Downcast along a virtual inheritance chain from base to the most derived type
BENCHMARK(DynCast<VChain<1>, VChain<0>>)->Name("VChain, 1 level");
BENCHMARK(DynCast<VChain<2>, VChain<0>>)->Name("VChain, 2 levels");
BENCHMARK(DynCast<VChain<3>, VChain<0>>)->Name("VChain, 3 levels");
BENCHMARK(DynCast<VChain<4>, VChain<0>>)->Name("VChain, 4 levels");
BENCHMARK(DynCast<VChain<5>, VChain<0>>)->Name("VChain, 5 levels");
// Downcast along a virtual inheritance chain from base to the middle of the chain
BENCHMARK(DynCast<VChain<2>, VChain<0>, VChain<1>>)->Name("VChain middle, 1 level");
BENCHMARK(DynCast<VChain<4>, VChain<0>, VChain<2>>)->Name("VChain middle, 2 levels");
BENCHMARK(DynCast<VChain<6>, VChain<0>, VChain<3>>)->Name("VChain middle, 3 levels");
BENCHMARK(DynCast<VChain<8>, VChain<0>, VChain<4>>)->Name("VChain middle, 4 levels");
// Downcast along a virtual chain that fails
BENCHMARK(DynCast<VChain<1>, VChain<0>, VChain<8>>)->Name("VChain fail, 1 level");
BENCHMARK(DynCast<VChain<2>, VChain<0>, VChain<8>>)->Name("VChain fail, 2 levels");
BENCHMARK(DynCast<VChain<3>, VChain<0>, VChain<8>>)->Name("VChain fail, 3 levels");
BENCHMARK(DynCast<VChain<4>, VChain<0>, VChain<8>>)->Name("VChain fail, 4 levels");
BENCHMARK(DynCast<VChain<5>, VChain<0>, VChain<8>>)->Name("VChain fail, 5 levels");
// Downcast along a DAG from base to the most derived type
BENCHMARK(DynCast<Dag<0, 3>, Dag<3, 0>>)->Name("DAG rightmost, 3 levels");
BENCHMARK(DynCast<Dag<0, 4>, Dag<4, 0>>)->Name("DAG rightmost, 4 levels");
BENCHMARK(DynCast<Dag<0, 5>, Dag<5, 0>>)->Name("DAG rightmost, 5 levels");
BENCHMARK(DynCast<Dag<0, 3>, Dag<0, 0>>)->Name("DAG leftmost, 3 levels");
BENCHMARK(DynCast<Dag<0, 4>, Dag<0, 0>>)->Name("DAG leftmost, 4 levels");
BENCHMARK(DynCast<Dag<0, 5>, Dag<0, 0>>)->Name("DAG leftmost, 5 levels");
// Downcast along a DAG from base to the middle of the DAG
BENCHMARK(DynCast<Dag<0, 4>, Dag<4, 0>, Dag<3, 1>>)->Name("DAG rightmost middle, 1 level");
BENCHMARK(DynCast<Dag<0, 4>, Dag<4, 0>, Dag<2, 2>>)->Name("DAG rightmost middle, 2 levels");
BENCHMARK(DynCast<Dag<0, 4>, Dag<4, 0>, Dag<1, 3>>)->Name("DAG rightmost middle, 3 levels");
BENCHMARK(DynCast<Dag<0, 4>, Dag<0, 0>, Dag<0, 1>>)->Name("DAG leftmost middle, 1 level");
BENCHMARK(DynCast<Dag<0, 4>, Dag<0, 0>, Dag<0, 2>>)->Name("DAG leftmost middle, 2 levels");
BENCHMARK(DynCast<Dag<0, 4>, Dag<0, 0>, Dag<0, 3>>)->Name("DAG leftmost middle, 3 levels");
// Sidecast along a DAG
BENCHMARK(DynCast<Dag<0, 3>, Dag<3, 0>, Dag<0, 0>>)->Name("DAG sidecast, 3 levels");
BENCHMARK(DynCast<Dag<0, 3>, Dag<2, 1>, Dag<0, 1>>)->Name("DAG sidecast, 2 levels");
BENCHMARK(DynCast<Dag<0, 3>, Dag<1, 2>, Dag<0, 2>>)->Name("DAG sidecast, 1 level");
// Sidecast along a DAG that fails
BENCHMARK(DynCast<Dag<0, 3>, Dag<3, 0>, Dag<0, 4>>)->Name("DAG sidecast fail, 3 levels");
BENCHMARK(DynCast<Dag<0, 3>, Dag<2, 1>, Dag<0, 4>>)->Name("DAG sidecast fail, 2 levels");
BENCHMARK(DynCast<Dag<0, 3>, Dag<1, 2>, Dag<0, 4>>)->Name("DAG sidecast fail, 1 level");
// Downcast along a virtual inheritance DAG from base to the most derived type
BENCHMARK(DynCast<VDag<0, 3>, VDag<3, 0>>)->Name("VDAG rightmost, 3 levels");
BENCHMARK(DynCast<VDag<0, 4>, VDag<4, 0>>)->Name("VDAG rightmost, 4 levels");
BENCHMARK(DynCast<VDag<0, 5>, VDag<5, 0>>)->Name("VDAG rightmost, 5 levels");
BENCHMARK(DynCast<VDag<0, 3>, VDag<0, 0>>)->Name("VDAG leftmost, 3 levels");
BENCHMARK(DynCast<VDag<0, 4>, VDag<0, 0>>)->Name("VDAG leftmost, 4 levels");
BENCHMARK(DynCast<VDag<0, 5>, VDag<0, 0>>)->Name("VDAG leftmost, 5 levels");
// Downcast along a virtual inheritance DAG from base to the middle of the DAG
BENCHMARK(DynCast<VDag<0, 3>, VDag<3, 0>, VDag<2, 1>>)->Name("VDAG rightmost middle, 1 level");
BENCHMARK(DynCast<VDag<0, 4>, VDag<4, 0>, VDag<2, 2>>)->Name("VDAG rightmost middle, 2 levels");
BENCHMARK(DynCast<VDag<0, 5>, VDag<5, 0>, VDag<2, 3>>)->Name("VDAG rightmost middle, 3 levels");
BENCHMARK(DynCast<VDag<0, 3>, VDag<0, 0>, VDag<0, 1>>)->Name("VDAG leftmost middle, 1 level");
BENCHMARK(DynCast<VDag<0, 4>, VDag<0, 0>, VDag<0, 2>>)->Name("VDAG leftmost middle, 2 levels");
BENCHMARK(DynCast<VDag<0, 5>, VDag<0, 0>, VDag<0, 3>>)->Name("VDAG leftmost middle, 3 levels");
// Sidecast along a virtual inheritance DAG
BENCHMARK(DynCast<VDag<0, 3>, VDag<3, 0>, VDag<0, 0>>)->Name("VDAG sidecast, 3 levels");
BENCHMARK(DynCast<VDag<0, 3>, VDag<2, 1>, VDag<0, 1>>)->Name("VDAG sidecast, 2 levels");
BENCHMARK(DynCast<VDag<0, 3>, VDag<1, 2>, VDag<0, 2>>)->Name("VDAG sidecast, 1 level");
// Sidecast along a virtual inheritance DAG that fails
BENCHMARK(DynCast<VDag<0, 3>, VDag<3, 0>, VDag<0, 4>>)->Name("VDAG sidecast fail, 3 levels");
BENCHMARK(DynCast<VDag<0, 3>, VDag<2, 1>, VDag<0, 4>>)->Name("VDAG sidecast fail, 2 levels");
BENCHMARK(DynCast<VDag<0, 3>, VDag<1, 2>, VDag<0, 4>>)->Name("VDAG sidecast fail, 1 level");
// Cast to complete object pointer
BENCHMARK(DynCast<Chain<8>, Chain<0>, void>)->Name("Chain to complete");
BENCHMARK(DynCast<VChain<5>, VChain<0>, void>)->Name("VChain to complete");
BENCHMARK(DynCast<Dag<0, 3>, Dag<3, 0>, void>)->Name("DAG to complete");
BENCHMARK(DynCast<VDag<0, 3>, VDag<3, 0>, void>)->Name("VDAG to complete");
// Static cast as the baseline.
BENCHMARK(StaticCast)->Name("Static");
BENCHMARK_MAIN();
Benchmark libsupc++ libcxxabi-before libcxxabi-after
Chain, 1 level 6.76 10.1 3.54
Chain, 2 levels 6.67 10.9 3.2
Chain, 3 levels 6.6 11.9 3.27
Chain, 4 levels 6.94 14.3 3.19
Chain, 5 levels 6.55 15.9 3.1
Chain, 6 levels 6.68 18.5 3.05
Chain, 7 levels 6.89 20.1 3.04
Chain, 8 levels 6.58 22.2 3.04
Chain, 9 levels 6.64 25.2 3.04
Chain middle, 1 level 17 11.6 8.71
Chain middle, 2 levels 24.4 15.8 10.6
Chain middle, 3 levels 28.1 20.6 12.8
Chain middle, 4 levels 35.3 25.1 14.9
Chain fail, 1 level 13.6 8.08 12.7
Chain fail, 2 levels 23.2 10.3 17
Chain fail, 3 levels 35.8 12.5 21.2
Chain fail, 4 levels 44.1 14.8 25.8
Chain fail, 5 levels 50.8 17.2 31.4
Chain fail, 6 levels 58.1 19.6 35.3
Chain fail, 7 levels 65.4 21.4 38.9
Chain fail, 8 levels 72.6 23.5 43.4
Vchain, 1 level 18.2 9.26 9.57
Vchain, 2 levels 24.3 13.7 14.1
Vchain, 3 levels 30 17.8 17.6
Vchain, 4 levels 35.8 22.2 22.1
Vchain, 5 levels 53.3 26.6 26.4
Vchain middle, 1 level 31.5 13.7 14.5
Vchain middle, 2 levels 63.6 21.5 21.7
Vchain middle, 3 levels 86.8 28.9 28.9
Vchain middle, 4 levels 120 37.1 37.2
Vchain fail, 1 level 18.6 8.37 8.97
Vchain fail, 2 levels 31.7 12 12.7
Vchain fail, 3 levels 44.2 15.6 16
Vchain fail, 4 levels 58 19.3 19.2
Vchain fail, 5 levels 77.4 22.7 23.1
DAG rightmost, 3 levels 7.65 63 3.06
DAG rightmost, 4 levels 7.6 128 3.1
DAG rightmost, 5 levels 7.57 264 3.06
DAG leftmost, 3 levels 10.1 19.1 3.07
DAG leftmost, 4 levels 10 24.3 3.07
DAG leftmost, 5 levels 10 28.1 3.07
DAG rightmost middle, 1 level 36.3 112 117
DAG rightmost middle, 2 levels 26.9 116 102
DAG rightmost middle, 3 levels 17.2 120 71.2
DAG leftmost middle, 1 level 47.7 100 21.1
DAG leftmost middle, 2 levels 35.3 92 16.6
DAG leftmost middle, 3 levels 22.4 71.1 11.6
DAG sidecast, 3 levels 123 55.2 57.6
DAG sidecast, 2 levels 92.5 51.4 53.4
DAG sidecast, 1 level 25.1 36.5 37.4
DAG sidecast fail, 3 levels 125 54.7 58.8
DAG sidecast fail, 2 levels 109 47.2 51.3
DAG sidecast fail, 1 level 75.5 34.9 37.8
VDAG rightmost, 3 levels 20.5 61.6 62
VDAG rightmost, 4 levels 25.1 126 128
VDAG rightmost, 5 levels 30 256 256
VDAG leftmost, 3 levels 56.1 19.6 19.9
VDAG leftmost, 4 levels 102 24.6 24.5
VDAG leftmost, 5 levels 191 29 29.6
VDAG rightmost middle, 1 level 117 56.8 57.9
VDAG rightmost middle, 2 levels 245 117 127
VDAG rightmost middle, 3 levels 507 244 238
VDAG leftmost middle, 1 level 128 53 55
VDAG leftmost middle, 2 levels 241 101 101
VDAG leftmost middle, 3 levels 529 188 189
VDAG sidecast, 3 levels 125 57.2 56.9
VDAG sidecast, 2 levels 97.6 49 50.1
VDAG sidecast, 1 level 24.8 36.8 38.1
VDAG sidecast fail, 3 levels 125 56.9 56.7
VDAG sidecast fail, 2 levels 113 48.2 48.9
VDAG sidecast fail, 1 level 83.2 33.9 35.6
Chain to complete 0.306 0.305 0.306
Vchain to complete 0.305 0.305 0.305
DAG to complete 0.305 0.305 0.306
VDAG to complete 0.612 0.611 0.614
Static 0.305 0.305 0.305
@Lancern
Copy link
Author

Lancern commented Nov 4, 2022

图片

@Lancern
Copy link
Author

Lancern commented Nov 4, 2022

图片

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment