Revert "[libc] Use best-fit binary trie to make malloc logarithmic" (#117065)
[llvm-project.git] / libcxx / test / benchmarks / function.bench.cpp
blobe607162d23b72f22e96e98c8cbec8e4fe0f0a393
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 //===----------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
11 #include <cstdint>
12 #include <functional>
13 #include <memory>
14 #include <string>
15 #include <utility>
17 #include "CartesianBenchmarks.h"
18 #include "benchmark/benchmark.h"
19 #include "test_macros.h"
21 namespace {
23 enum class FunctionType {
24 Null,
25 FunctionPointer,
26 MemberFunctionPointer,
27 MemberPointer,
28 SmallTrivialFunctor,
29 SmallNonTrivialFunctor,
30 LargeTrivialFunctor,
31 LargeNonTrivialFunctor
34 struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {
35 static constexpr const char* Names[] = {
36 "Null",
37 "FuncPtr",
38 "MemFuncPtr",
39 "MemPtr",
40 "SmallTrivialFunctor",
41 "SmallNonTrivialFunctor",
42 "LargeTrivialFunctor",
43 "LargeNonTrivialFunctor"};
46 enum class Opacity { kOpaque, kTransparent };
48 struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
49 static constexpr const char* Names[] = {"Opaque", "Transparent"};
52 struct S {
53 int function() const { return 0; }
54 int field = 0;
57 int FunctionWithS(const S*) { return 0; }
59 struct SmallTrivialFunctor {
60 int operator()(const S*) const { return 0; }
62 struct SmallNonTrivialFunctor {
63 SmallNonTrivialFunctor() {}
64 SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {}
65 ~SmallNonTrivialFunctor() {}
66 int operator()(const S*) const { return 0; }
68 struct LargeTrivialFunctor {
69 LargeTrivialFunctor() {
70 // Do not spend time initializing the padding.
72 int padding[16];
73 int operator()(const S*) const { return 0; }
75 struct LargeNonTrivialFunctor {
76 int padding[16];
77 LargeNonTrivialFunctor() {
78 // Do not spend time initializing the padding.
80 LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {}
81 ~LargeNonTrivialFunctor() {}
82 int operator()(const S*) const { return 0; }
85 using Function = std::function<int(const S*)>;
87 TEST_ALWAYS_INLINE
88 inline Function MakeFunction(FunctionType type, bool opaque = false) {
89 switch (type) {
90 case FunctionType::Null:
91 return nullptr;
92 case FunctionType::FunctionPointer:
93 return maybeOpaque(FunctionWithS, opaque);
94 case FunctionType::MemberFunctionPointer:
95 return maybeOpaque(&S::function, opaque);
96 case FunctionType::MemberPointer:
97 return maybeOpaque(&S::field, opaque);
98 case FunctionType::SmallTrivialFunctor:
99 return maybeOpaque(SmallTrivialFunctor{}, opaque);
100 case FunctionType::SmallNonTrivialFunctor:
101 return maybeOpaque(SmallNonTrivialFunctor{}, opaque);
102 case FunctionType::LargeTrivialFunctor:
103 return maybeOpaque(LargeTrivialFunctor{}, opaque);
104 case FunctionType::LargeNonTrivialFunctor:
105 return maybeOpaque(LargeNonTrivialFunctor{}, opaque);
107 std::unreachable();
110 template <class Opacity, class FunctionType>
111 struct ConstructAndDestroy {
112 static void run(benchmark::State& state) {
113 for (auto _ : state) {
114 if (Opacity() == ::Opacity::kOpaque) {
115 benchmark::DoNotOptimize(MakeFunction(FunctionType(), true));
116 } else {
117 MakeFunction(FunctionType());
122 static std::string name() { return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name(); }
125 template <class FunctionType>
126 struct Copy {
127 static void run(benchmark::State& state) {
128 auto value = MakeFunction(FunctionType());
129 for (auto _ : state) {
130 benchmark::DoNotOptimize(value);
131 auto copy = value; // NOLINT
132 benchmark::DoNotOptimize(copy);
136 static std::string name() { return "BM_Copy" + FunctionType::name(); }
139 template <class FunctionType>
140 struct Move {
141 static void run(benchmark::State& state) {
142 Function values[2] = {MakeFunction(FunctionType())};
143 int i = 0;
144 for (auto _ : state) {
145 benchmark::DoNotOptimize(values);
146 benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));
147 i ^= 1;
151 static std::string name() { return "BM_Move" + FunctionType::name(); }
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]);
164 static bool skip() { return Function1() > Function2(); }
166 static std::string name() { return "BM_Swap" + Function1::name() + Function2::name(); }
169 template <class FunctionType>
170 struct OperatorBool {
171 static void run(benchmark::State& state) {
172 auto f = MakeFunction(FunctionType());
173 for (auto _ : state) {
174 benchmark::DoNotOptimize(f);
175 benchmark::DoNotOptimize(static_cast<bool>(f));
179 static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }
182 template <class FunctionType>
183 struct Invoke {
184 static void run(benchmark::State& state) {
185 S s;
186 auto value = MakeFunction(FunctionType());
187 for (auto _ : state) {
188 benchmark::DoNotOptimize(value);
189 benchmark::DoNotOptimize(value(&s));
193 static bool skip() { return FunctionType() == ::FunctionType::Null; }
195 static std::string name() { return "BM_Invoke" + FunctionType::name(); }
198 template <class FunctionType>
199 struct InvokeInlined {
200 static void run(benchmark::State& state) {
201 S s;
202 for (auto _ : state) {
203 MakeFunction(FunctionType())(&s);
207 static bool skip() { return FunctionType() == ::FunctionType::Null; }
209 static std::string name() { return "BM_InvokeInlined" + FunctionType::name(); }
212 } // namespace
214 int main(int argc, char** argv) {
215 benchmark::Initialize(&argc, argv);
216 if (benchmark::ReportUnrecognizedArguments(argc, argv))
217 return 1;
219 makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity, AllFunctionTypes>();
220 makeCartesianProductBenchmark<Copy, AllFunctionTypes>();
221 makeCartesianProductBenchmark<Move, AllFunctionTypes>();
222 makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();
223 makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();
224 makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();
225 makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();
226 benchmark::RunSpecifiedBenchmarks();