-
-
Save Lancern/212a26a3144343f459428dffe202cde0 to your computer and use it in GitHub Desktop.
dynamic_cast performance benchmark suite and results
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment