llvm-project

Форк
0
/
function.bench.cpp 
223 строки · 6.3 Кб
1
//===----------------------------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8

9
#include <cstdint>
10
#include <functional>
11
#include <memory>
12
#include <string>
13

14
#include "CartesianBenchmarks.h"
15
#include "benchmark/benchmark.h"
16
#include "test_macros.h"
17

18
namespace {
19

20
enum class FunctionType {
21
  Null,
22
  FunctionPointer,
23
  MemberFunctionPointer,
24
  MemberPointer,
25
  SmallTrivialFunctor,
26
  SmallNonTrivialFunctor,
27
  LargeTrivialFunctor,
28
  LargeNonTrivialFunctor
29
};
30

31
struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {
32
  static constexpr const char* Names[] = {
33
      "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() { return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name(); }
119
};
120

121
template <class FunctionType>
122
struct Copy {
123
  static void run(benchmark::State& state) {
124
    auto value = MakeFunction(FunctionType());
125
    for (auto _ : state) {
126
      benchmark::DoNotOptimize(value);
127
      auto copy = value; // NOLINT
128
      benchmark::DoNotOptimize(copy);
129
    }
130
  }
131

132
  static std::string name() { return "BM_Copy" + FunctionType::name(); }
133
};
134

135
template <class FunctionType>
136
struct Move {
137
  static void run(benchmark::State& state) {
138
    Function values[2] = {MakeFunction(FunctionType())};
139
    int i              = 0;
140
    for (auto _ : state) {
141
      benchmark::DoNotOptimize(values);
142
      benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));
143
      i ^= 1;
144
    }
145
  }
146

147
  static std::string name() { return "BM_Move" + FunctionType::name(); }
148
};
149

150
template <class Function1, class Function2>
151
struct Swap {
152
  static void run(benchmark::State& state) {
153
    Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())};
154
    for (auto _ : state) {
155
      benchmark::DoNotOptimize(values);
156
      values[0].swap(values[1]);
157
    }
158
  }
159

160
  static bool skip() { return Function1() > Function2(); }
161

162
  static std::string name() { return "BM_Swap" + Function1::name() + Function2::name(); }
163
};
164

165
template <class FunctionType>
166
struct OperatorBool {
167
  static void run(benchmark::State& state) {
168
    auto f = MakeFunction(FunctionType());
169
    for (auto _ : state) {
170
      benchmark::DoNotOptimize(f);
171
      benchmark::DoNotOptimize(static_cast<bool>(f));
172
    }
173
  }
174

175
  static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }
176
};
177

178
template <class FunctionType>
179
struct Invoke {
180
  static void run(benchmark::State& state) {
181
    S s;
182
    const auto value = MakeFunction(FunctionType());
183
    for (auto _ : state) {
184
      benchmark::DoNotOptimize(value);
185
      benchmark::DoNotOptimize(value(&s));
186
    }
187
  }
188

189
  static bool skip() { return FunctionType() == ::FunctionType::Null; }
190

191
  static std::string name() { return "BM_Invoke" + FunctionType::name(); }
192
};
193

194
template <class FunctionType>
195
struct InvokeInlined {
196
  static void run(benchmark::State& state) {
197
    S s;
198
    for (auto _ : state) {
199
      MakeFunction(FunctionType())(&s);
200
    }
201
  }
202

203
  static bool skip() { return FunctionType() == ::FunctionType::Null; }
204

205
  static std::string name() { return "BM_InvokeInlined" + FunctionType::name(); }
206
};
207

208
} // namespace
209

210
int main(int argc, char** argv) {
211
  benchmark::Initialize(&argc, argv);
212
  if (benchmark::ReportUnrecognizedArguments(argc, argv))
213
    return 1;
214

215
  makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity, AllFunctionTypes>();
216
  makeCartesianProductBenchmark<Copy, AllFunctionTypes>();
217
  makeCartesianProductBenchmark<Move, AllFunctionTypes>();
218
  makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();
219
  makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();
220
  makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();
221
  makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();
222
  benchmark::RunSpecifiedBenchmarks();
223
}
224

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.