| // Copyright 2022 The Dawn & Tint Authors | |
| // | |
| // Redistribution and use in source and binary forms, with or without | |
| // modification, are permitted provided that the following conditions are met: | |
| // | |
| // 1. Redistributions of source code must retain the above copyright notice, this | |
| // list of conditions and the following disclaimer. | |
| // | |
| // 2. Redistributions in binary form must reproduce the above copyright notice, | |
| // this list of conditions and the following disclaimer in the documentation | |
| // and/or other materials provided with the distribution. | |
| // | |
| // 3. Neither the name of the copyright holder nor the names of its | |
| // contributors may be used to endorse or promote products derived from | |
| // this software without specific prior written permission. | |
| // | |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
| // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
| // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
| // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| #include <memory> | |
| #include "benchmark/benchmark.h" | |
| #include "src/tint/utils/rtti/switch.h" | |
| namespace tint::test { | |
| struct Base : public Castable<Base> {}; | |
| struct A : public Castable<A, Base> {}; | |
| struct AA : public Castable<AA, A> {}; | |
| struct AAA : public Castable<AAA, AA> {}; | |
| struct AAB : public Castable<AAB, AA> {}; | |
| struct AAC : public Castable<AAC, AA> {}; | |
| struct AB : public Castable<AB, A> {}; | |
| struct ABA : public Castable<ABA, AB> {}; | |
| struct ABB : public Castable<ABB, AB> {}; | |
| struct ABC : public Castable<ABC, AB> {}; | |
| struct AC : public Castable<AC, A> {}; | |
| struct ACA : public Castable<ACA, AC> {}; | |
| struct ACB : public Castable<ACB, AC> {}; | |
| struct ACC : public Castable<ACC, AC> {}; | |
| struct B : public Castable<B, Base> {}; | |
| struct BA : public Castable<BA, B> {}; | |
| struct BAA : public Castable<BAA, BA> {}; | |
| struct BAB : public Castable<BAB, BA> {}; | |
| struct BAC : public Castable<BAC, BA> {}; | |
| struct BB : public Castable<BB, B> {}; | |
| struct BBA : public Castable<BBA, BB> {}; | |
| struct BBB : public Castable<BBB, BB> {}; | |
| struct BBC : public Castable<BBC, BB> {}; | |
| struct BC : public Castable<BC, B> {}; | |
| struct BCA : public Castable<BCA, BC> {}; | |
| struct BCB : public Castable<BCB, BC> {}; | |
| struct BCC : public Castable<BCC, BC> {}; | |
| struct C : public Castable<C, Base> {}; | |
| struct CA : public Castable<CA, C> {}; | |
| struct CAA : public Castable<CAA, CA> {}; | |
| struct CAB : public Castable<CAB, CA> {}; | |
| struct CAC : public Castable<CAC, CA> {}; | |
| struct CB : public Castable<CB, C> {}; | |
| struct CBA : public Castable<CBA, CB> {}; | |
| struct CBB : public Castable<CBB, CB> {}; | |
| struct CBC : public Castable<CBC, CB> {}; | |
| struct CC : public Castable<CC, C> {}; | |
| struct CCA : public Castable<CCA, CC> {}; | |
| struct CCB : public Castable<CCB, CC> {}; | |
| struct CCC : public Castable<CCC, CC> {}; | |
| namespace { | |
| using AllTypes = std::tuple<Base, | |
| A, | |
| AA, | |
| AAA, | |
| AAB, | |
| AAC, | |
| AB, | |
| ABA, | |
| ABB, | |
| ABC, | |
| AC, | |
| ACA, | |
| ACB, | |
| ACC, | |
| B, | |
| BA, | |
| BAA, | |
| BAB, | |
| BAC, | |
| BB, | |
| BBA, | |
| BBB, | |
| BBC, | |
| BC, | |
| BCA, | |
| BCB, | |
| BCC, | |
| C, | |
| CA, | |
| CAA, | |
| CAB, | |
| CAC, | |
| CB, | |
| CBA, | |
| CBB, | |
| CBC, | |
| CC, | |
| CCA, | |
| CCB, | |
| CCC>; | |
| std::vector<std::unique_ptr<Base>> MakeObjects() { | |
| std::vector<std::unique_ptr<Base>> out; | |
| out.emplace_back(std::make_unique<Base>()); | |
| out.emplace_back(std::make_unique<A>()); | |
| out.emplace_back(std::make_unique<AA>()); | |
| out.emplace_back(std::make_unique<AAA>()); | |
| out.emplace_back(std::make_unique<AAB>()); | |
| out.emplace_back(std::make_unique<AAC>()); | |
| out.emplace_back(std::make_unique<AB>()); | |
| out.emplace_back(std::make_unique<ABA>()); | |
| out.emplace_back(std::make_unique<ABB>()); | |
| out.emplace_back(std::make_unique<ABC>()); | |
| out.emplace_back(std::make_unique<AC>()); | |
| out.emplace_back(std::make_unique<ACA>()); | |
| out.emplace_back(std::make_unique<ACB>()); | |
| out.emplace_back(std::make_unique<ACC>()); | |
| out.emplace_back(std::make_unique<B>()); | |
| out.emplace_back(std::make_unique<BA>()); | |
| out.emplace_back(std::make_unique<BAA>()); | |
| out.emplace_back(std::make_unique<BAB>()); | |
| out.emplace_back(std::make_unique<BAC>()); | |
| out.emplace_back(std::make_unique<BB>()); | |
| out.emplace_back(std::make_unique<BBA>()); | |
| out.emplace_back(std::make_unique<BBB>()); | |
| out.emplace_back(std::make_unique<BBC>()); | |
| out.emplace_back(std::make_unique<BC>()); | |
| out.emplace_back(std::make_unique<BCA>()); | |
| out.emplace_back(std::make_unique<BCB>()); | |
| out.emplace_back(std::make_unique<BCC>()); | |
| out.emplace_back(std::make_unique<C>()); | |
| out.emplace_back(std::make_unique<CA>()); | |
| out.emplace_back(std::make_unique<CAA>()); | |
| out.emplace_back(std::make_unique<CAB>()); | |
| out.emplace_back(std::make_unique<CAC>()); | |
| out.emplace_back(std::make_unique<CB>()); | |
| out.emplace_back(std::make_unique<CBA>()); | |
| out.emplace_back(std::make_unique<CBB>()); | |
| out.emplace_back(std::make_unique<CBC>()); | |
| out.emplace_back(std::make_unique<CC>()); | |
| out.emplace_back(std::make_unique<CCA>()); | |
| out.emplace_back(std::make_unique<CCB>()); | |
| out.emplace_back(std::make_unique<CCC>()); | |
| return out; | |
| } | |
| void CastableLargeSwitch(::benchmark::State& state) { | |
| auto objects = MakeObjects(); | |
| size_t i = 0; | |
| for (auto _ : state) { | |
| auto* object = objects[i % objects.size()].get(); | |
| Switch( | |
| object, // | |
| [&](const AAA*) { ::benchmark::DoNotOptimize(i += 40); }, | |
| [&](const AAB*) { ::benchmark::DoNotOptimize(i += 50); }, | |
| [&](const AAC*) { ::benchmark::DoNotOptimize(i += 60); }, | |
| [&](const ABA*) { ::benchmark::DoNotOptimize(i += 80); }, | |
| [&](const ABB*) { ::benchmark::DoNotOptimize(i += 90); }, | |
| [&](const ABC*) { ::benchmark::DoNotOptimize(i += 100); }, | |
| [&](const ACA*) { ::benchmark::DoNotOptimize(i += 120); }, | |
| [&](const ACB*) { ::benchmark::DoNotOptimize(i += 130); }, | |
| [&](const ACC*) { ::benchmark::DoNotOptimize(i += 140); }, | |
| [&](const BAA*) { ::benchmark::DoNotOptimize(i += 170); }, | |
| [&](const BAB*) { ::benchmark::DoNotOptimize(i += 180); }, | |
| [&](const BAC*) { ::benchmark::DoNotOptimize(i += 190); }, | |
| [&](const BBA*) { ::benchmark::DoNotOptimize(i += 210); }, | |
| [&](const BBB*) { ::benchmark::DoNotOptimize(i += 220); }, | |
| [&](const BBC*) { ::benchmark::DoNotOptimize(i += 230); }, | |
| [&](const BCA*) { ::benchmark::DoNotOptimize(i += 250); }, | |
| [&](const BCB*) { ::benchmark::DoNotOptimize(i += 260); }, | |
| [&](const BCC*) { ::benchmark::DoNotOptimize(i += 270); }, | |
| [&](const CA*) { ::benchmark::DoNotOptimize(i += 290); }, | |
| [&](const CAA*) { ::benchmark::DoNotOptimize(i += 300); }, | |
| [&](const CAB*) { ::benchmark::DoNotOptimize(i += 310); }, | |
| [&](const CAC*) { ::benchmark::DoNotOptimize(i += 320); }, | |
| [&](const CBA*) { ::benchmark::DoNotOptimize(i += 340); }, | |
| [&](const CBB*) { ::benchmark::DoNotOptimize(i += 350); }, | |
| [&](const CBC*) { ::benchmark::DoNotOptimize(i += 360); }, | |
| [&](const CCA*) { ::benchmark::DoNotOptimize(i += 380); }, | |
| [&](const CCB*) { ::benchmark::DoNotOptimize(i += 390); }, | |
| [&](const CCC*) { ::benchmark::DoNotOptimize(i += 400); }, | |
| [&](Default) { ::benchmark::DoNotOptimize(i += 123); }); | |
| i = (i * 31) ^ (i << 5); | |
| } | |
| } | |
| BENCHMARK(CastableLargeSwitch); | |
| void CastableMediumSwitch(::benchmark::State& state) { | |
| auto objects = MakeObjects(); | |
| size_t i = 0; | |
| for (auto _ : state) { | |
| auto* object = objects[i % objects.size()].get(); | |
| Switch( | |
| object, // | |
| [&](const ACB*) { ::benchmark::DoNotOptimize(i += 130); }, | |
| [&](const BAA*) { ::benchmark::DoNotOptimize(i += 170); }, | |
| [&](const BAB*) { ::benchmark::DoNotOptimize(i += 180); }, | |
| [&](const BBA*) { ::benchmark::DoNotOptimize(i += 210); }, | |
| [&](const BBB*) { ::benchmark::DoNotOptimize(i += 220); }, | |
| [&](const CAA*) { ::benchmark::DoNotOptimize(i += 300); }, | |
| [&](const CCA*) { ::benchmark::DoNotOptimize(i += 380); }, | |
| [&](const CCB*) { ::benchmark::DoNotOptimize(i += 390); }, | |
| [&](const CCC*) { ::benchmark::DoNotOptimize(i += 400); }, | |
| [&](Default) { ::benchmark::DoNotOptimize(i += 123); }); | |
| i = (i * 31) ^ (i << 5); | |
| } | |
| } | |
| BENCHMARK(CastableMediumSwitch); | |
| void CastableSmallSwitch(::benchmark::State& state) { | |
| auto objects = MakeObjects(); | |
| size_t i = 0; | |
| for (auto _ : state) { | |
| auto* object = objects[i % objects.size()].get(); | |
| Switch( | |
| object, // | |
| [&](const AAB*) { ::benchmark::DoNotOptimize(i += 30); }, | |
| [&](const CAC*) { ::benchmark::DoNotOptimize(i += 290); }, | |
| [&](const CAA*) { ::benchmark::DoNotOptimize(i += 300); }); | |
| i = (i * 31) ^ (i << 5); | |
| } | |
| } | |
| BENCHMARK(CastableSmallSwitch); | |
| } // namespace | |
| } // namespace tint::test | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::Base); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::A); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::AA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::AAA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::AAB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::AAC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::AB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::ABA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::ABB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::ABC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::AC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::ACA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::ACB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::ACC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::B); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BAA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BAB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BAC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BBA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BBB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BBC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BCA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BCB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::BCC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::C); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CAA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CAB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CAC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CBA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CBB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CBC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CC); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CCA); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CCB); | |
| TINT_INSTANTIATE_TYPEINFO(tint::test::CCC); |