libcxx

libcxx mirror with random patches
git clone https://git.neptards.moe/neptards/libcxx.git
Log | Files | Refs

function.bench.cpp (6745B)


      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include <cstdint>
     11 #include <functional>
     12 #include <memory>
     13 #include <string>
     14 
     15 #include "CartesianBenchmarks.hpp"
     16 #include "benchmark/benchmark.h"
     17 #include "test_macros.h"
     18 
     19 namespace {
     20 
     21 enum class FunctionType {
     22   Null,
     23   FunctionPointer,
     24   MemberFunctionPointer,
     25   MemberPointer,
     26   SmallTrivialFunctor,
     27   SmallNonTrivialFunctor,
     28   LargeTrivialFunctor,
     29   LargeNonTrivialFunctor
     30 };
     31 
     32 struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {
     33   static constexpr const char* Names[] = {"Null",
     34                                           "FuncPtr",
     35                                           "MemFuncPtr",
     36                                           "MemPtr",
     37                                           "SmallTrivialFunctor",
     38                                           "SmallNonTrivialFunctor",
     39                                           "LargeTrivialFunctor",
     40                                           "LargeNonTrivialFunctor"};
     41 };
     42 
     43 enum class Opacity { kOpaque, kTransparent };
     44 
     45 struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
     46   static constexpr const char* Names[] = {"Opaque", "Transparent"};
     47 };
     48 
     49 struct S {
     50   int function() const { return 0; }
     51   int field = 0;
     52 };
     53 
     54 int FunctionWithS(const S*) { return 0; }
     55 
     56 struct SmallTrivialFunctor {
     57   int operator()(const S*) const { return 0; }
     58 };
     59 struct SmallNonTrivialFunctor {
     60   SmallNonTrivialFunctor() {}
     61   SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {}
     62   ~SmallNonTrivialFunctor() {}
     63   int operator()(const S*) const { return 0; }
     64 };
     65 struct LargeTrivialFunctor {
     66   LargeTrivialFunctor() {
     67       // Do not spend time initializing the padding.
     68   }
     69   int padding[16];
     70   int operator()(const S*) const { return 0; }
     71 };
     72 struct LargeNonTrivialFunctor {
     73   int padding[16];
     74   LargeNonTrivialFunctor() {
     75       // Do not spend time initializing the padding.
     76   }
     77   LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {}
     78   ~LargeNonTrivialFunctor() {}
     79   int operator()(const S*) const { return 0; }
     80 };
     81 
     82 using Function = std::function<int(const S*)>;
     83 
     84 TEST_ALWAYS_INLINE
     85 inline Function MakeFunction(FunctionType type, bool opaque = false) {
     86   switch (type) {
     87     case FunctionType::Null:
     88       return nullptr;
     89     case FunctionType::FunctionPointer:
     90       return maybeOpaque(FunctionWithS, opaque);
     91     case FunctionType::MemberFunctionPointer:
     92       return maybeOpaque(&S::function, opaque);
     93     case FunctionType::MemberPointer:
     94       return maybeOpaque(&S::field, opaque);
     95     case FunctionType::SmallTrivialFunctor:
     96       return maybeOpaque(SmallTrivialFunctor{}, opaque);
     97     case FunctionType::SmallNonTrivialFunctor:
     98       return maybeOpaque(SmallNonTrivialFunctor{}, opaque);
     99     case FunctionType::LargeTrivialFunctor:
    100       return maybeOpaque(LargeTrivialFunctor{}, opaque);
    101     case FunctionType::LargeNonTrivialFunctor:
    102       return maybeOpaque(LargeNonTrivialFunctor{}, opaque);
    103   }
    104 }
    105 
    106 template <class Opacity, class FunctionType>
    107 struct ConstructAndDestroy {
    108   static void run(benchmark::State& state) {
    109     for (auto _ : state) {
    110       if (Opacity() == ::Opacity::kOpaque) {
    111         benchmark::DoNotOptimize(MakeFunction(FunctionType(), true));
    112       } else {
    113         MakeFunction(FunctionType());
    114       }
    115     }
    116   }
    117 
    118   static std::string name() {
    119     return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name();
    120   }
    121 };
    122 
    123 template <class FunctionType>
    124 struct Copy {
    125   static void run(benchmark::State& state) {
    126     auto value = MakeFunction(FunctionType());
    127     for (auto _ : state) {
    128       benchmark::DoNotOptimize(value);
    129       auto copy = value;  // NOLINT
    130       benchmark::DoNotOptimize(copy);
    131     }
    132   }
    133 
    134   static std::string name() { return "BM_Copy" + FunctionType::name(); }
    135 };
    136 
    137 template <class FunctionType>
    138 struct Move {
    139   static void run(benchmark::State& state) {
    140     Function values[2] = {MakeFunction(FunctionType())};
    141     int i = 0;
    142     for (auto _ : state) {
    143       benchmark::DoNotOptimize(values);
    144       benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));
    145       i ^= 1;
    146     }
    147   }
    148 
    149   static std::string name() {
    150     return "BM_Move" + FunctionType::name();
    151   }
    152 };
    153 
    154 template <class Function1, class Function2>
    155 struct Swap {
    156   static void run(benchmark::State& state) {
    157     Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())};
    158     for (auto _ : state) {
    159       benchmark::DoNotOptimize(values);
    160       values[0].swap(values[1]);
    161     }
    162   }
    163 
    164   static bool skip() { return Function1() > Function2(); }
    165 
    166   static std::string name() {
    167     return "BM_Swap" + Function1::name() + Function2::name();
    168   }
    169 };
    170 
    171 template <class FunctionType>
    172 struct OperatorBool {
    173   static void run(benchmark::State& state) {
    174     auto f = MakeFunction(FunctionType());
    175     for (auto _ : state) {
    176       benchmark::DoNotOptimize(f);
    177       benchmark::DoNotOptimize(static_cast<bool>(f));
    178     }
    179   }
    180 
    181   static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }
    182 };
    183 
    184 template <class FunctionType>
    185 struct Invoke {
    186   static void run(benchmark::State& state) {
    187     S s;
    188     const auto value = MakeFunction(FunctionType());
    189     for (auto _ : state) {
    190       benchmark::DoNotOptimize(value);
    191       benchmark::DoNotOptimize(value(&s));
    192     }
    193   }
    194 
    195   static bool skip() { return FunctionType() == ::FunctionType::Null; }
    196 
    197   static std::string name() { return "BM_Invoke" + FunctionType::name(); }
    198 };
    199 
    200 template <class FunctionType>
    201 struct InvokeInlined {
    202   static void run(benchmark::State& state) {
    203     S s;
    204     for (auto _ : state) {
    205       MakeFunction(FunctionType())(&s);
    206     }
    207   }
    208 
    209   static bool skip() { return FunctionType() == ::FunctionType::Null; }
    210 
    211   static std::string name() {
    212     return "BM_InvokeInlined" + FunctionType::name();
    213   }
    214 };
    215 
    216 }  // namespace
    217 
    218 int main(int argc, char** argv) {
    219   benchmark::Initialize(&argc, argv);
    220   if (benchmark::ReportUnrecognizedArguments(argc, argv))
    221     return 1;
    222 
    223   makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity,
    224                                 AllFunctionTypes>();
    225   makeCartesianProductBenchmark<Copy, AllFunctionTypes>();
    226   makeCartesianProductBenchmark<Move, AllFunctionTypes>();
    227   makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();
    228   makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();
    229   makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();
    230   makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();
    231   benchmark::RunSpecifiedBenchmarks();
    232 }