• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/functional/function_ref.h"
16 
17 #include <memory>
18 
19 #include "benchmark/benchmark.h"
20 #include "absl/base/attributes.h"
21 
22 namespace absl {
23 ABSL_NAMESPACE_BEGIN
24 namespace {
25 
26 int dummy = 0;
27 
FreeFunction()28 void FreeFunction() { benchmark::DoNotOptimize(dummy); }
29 
30 struct TrivialFunctor {
operator ()absl::__anon7b1e9cea0111::TrivialFunctor31   void operator()() const { benchmark::DoNotOptimize(dummy); }
32 };
33 
34 struct LargeFunctor {
operator ()absl::__anon7b1e9cea0111::LargeFunctor35   void operator()() const { benchmark::DoNotOptimize(this); }
36   std::string a, b, c;
37 };
38 
39 template <typename Function, typename... Args>
CallFunction(Function f,Args &&...args)40 void ABSL_ATTRIBUTE_NOINLINE CallFunction(Function f, Args&&... args) {
41   f(std::forward<Args>(args)...);
42 }
43 
44 template <typename Function, typename Callable, typename... Args>
ConstructAndCallFunctionBenchmark(benchmark::State & state,const Callable & c,Args &&...args)45 void ConstructAndCallFunctionBenchmark(benchmark::State& state,
46                                        const Callable& c, Args&&... args) {
47   for (auto _ : state) {
48     CallFunction<Function>(c, std::forward<Args>(args)...);
49   }
50 }
51 
BM_TrivialStdFunction(benchmark::State & state)52 void BM_TrivialStdFunction(benchmark::State& state) {
53   ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
54                                                            TrivialFunctor{});
55 }
56 BENCHMARK(BM_TrivialStdFunction);
57 
BM_TrivialFunctionRef(benchmark::State & state)58 void BM_TrivialFunctionRef(benchmark::State& state) {
59   ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state,
60                                                          TrivialFunctor{});
61 }
62 BENCHMARK(BM_TrivialFunctionRef);
63 
BM_LargeStdFunction(benchmark::State & state)64 void BM_LargeStdFunction(benchmark::State& state) {
65   ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
66                                                            LargeFunctor{});
67 }
68 BENCHMARK(BM_LargeStdFunction);
69 
BM_LargeFunctionRef(benchmark::State & state)70 void BM_LargeFunctionRef(benchmark::State& state) {
71   ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, LargeFunctor{});
72 }
73 BENCHMARK(BM_LargeFunctionRef);
74 
BM_FunPtrStdFunction(benchmark::State & state)75 void BM_FunPtrStdFunction(benchmark::State& state) {
76   ConstructAndCallFunctionBenchmark<std::function<void()>>(state, FreeFunction);
77 }
78 BENCHMARK(BM_FunPtrStdFunction);
79 
BM_FunPtrFunctionRef(benchmark::State & state)80 void BM_FunPtrFunctionRef(benchmark::State& state) {
81   ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, FreeFunction);
82 }
83 BENCHMARK(BM_FunPtrFunctionRef);
84 
85 // Doesn't include construction or copy overhead in the loop.
86 template <typename Function, typename Callable, typename... Args>
CallFunctionBenchmark(benchmark::State & state,const Callable & c,Args...args)87 void CallFunctionBenchmark(benchmark::State& state, const Callable& c,
88                            Args... args) {
89   Function f = c;
90   for (auto _ : state) {
91     benchmark::DoNotOptimize(&f);
92     f(args...);
93   }
94 }
95 
96 struct FunctorWithTrivialArgs {
operator ()absl::__anon7b1e9cea0111::FunctorWithTrivialArgs97   void operator()(int a, int b, int c) const {
98     benchmark::DoNotOptimize(a);
99     benchmark::DoNotOptimize(b);
100     benchmark::DoNotOptimize(c);
101   }
102 };
103 
BM_TrivialArgsStdFunction(benchmark::State & state)104 void BM_TrivialArgsStdFunction(benchmark::State& state) {
105   CallFunctionBenchmark<std::function<void(int, int, int)>>(
106       state, FunctorWithTrivialArgs{}, 1, 2, 3);
107 }
108 BENCHMARK(BM_TrivialArgsStdFunction);
109 
BM_TrivialArgsFunctionRef(benchmark::State & state)110 void BM_TrivialArgsFunctionRef(benchmark::State& state) {
111   CallFunctionBenchmark<FunctionRef<void(int, int, int)>>(
112       state, FunctorWithTrivialArgs{}, 1, 2, 3);
113 }
114 BENCHMARK(BM_TrivialArgsFunctionRef);
115 
116 struct FunctorWithNonTrivialArgs {
operator ()absl::__anon7b1e9cea0111::FunctorWithNonTrivialArgs117   void operator()(std::string a, std::string b, std::string c) const {
118     benchmark::DoNotOptimize(&a);
119     benchmark::DoNotOptimize(&b);
120     benchmark::DoNotOptimize(&c);
121   }
122 };
123 
BM_NonTrivialArgsStdFunction(benchmark::State & state)124 void BM_NonTrivialArgsStdFunction(benchmark::State& state) {
125   std::string a, b, c;
126   CallFunctionBenchmark<
127       std::function<void(std::string, std::string, std::string)>>(
128       state, FunctorWithNonTrivialArgs{}, a, b, c);
129 }
130 BENCHMARK(BM_NonTrivialArgsStdFunction);
131 
BM_NonTrivialArgsFunctionRef(benchmark::State & state)132 void BM_NonTrivialArgsFunctionRef(benchmark::State& state) {
133   std::string a, b, c;
134   CallFunctionBenchmark<
135       FunctionRef<void(std::string, std::string, std::string)>>(
136       state, FunctorWithNonTrivialArgs{}, a, b, c);
137 }
138 BENCHMARK(BM_NonTrivialArgsFunctionRef);
139 
140 }  // namespace
141 ABSL_NAMESPACE_END
142 }  // namespace absl
143