blob: 045305bfef30f007c15b554f3d07e5aa07ee8014 [file] [log] [blame]
Austin Schuhb4691e92020-12-31 12:37:18 -08001// 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
22namespace absl {
23ABSL_NAMESPACE_BEGIN
24namespace {
25
26int dummy = 0;
27
28void FreeFunction() { benchmark::DoNotOptimize(dummy); }
29
30struct TrivialFunctor {
31 void operator()() const { benchmark::DoNotOptimize(dummy); }
32};
33
34struct LargeFunctor {
35 void operator()() const { benchmark::DoNotOptimize(this); }
36 std::string a, b, c;
37};
38
39template <typename Function, typename... Args>
40void ABSL_ATTRIBUTE_NOINLINE CallFunction(Function f, Args&&... args) {
41 f(std::forward<Args>(args)...);
42}
43
44template <typename Function, typename Callable, typename... Args>
45void 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
52void BM_TrivialStdFunction(benchmark::State& state) {
53 ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
54 TrivialFunctor{});
55}
56BENCHMARK(BM_TrivialStdFunction);
57
58void BM_TrivialFunctionRef(benchmark::State& state) {
59 ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state,
60 TrivialFunctor{});
61}
62BENCHMARK(BM_TrivialFunctionRef);
63
64void BM_LargeStdFunction(benchmark::State& state) {
65 ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
66 LargeFunctor{});
67}
68BENCHMARK(BM_LargeStdFunction);
69
70void BM_LargeFunctionRef(benchmark::State& state) {
71 ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, LargeFunctor{});
72}
73BENCHMARK(BM_LargeFunctionRef);
74
75void BM_FunPtrStdFunction(benchmark::State& state) {
76 ConstructAndCallFunctionBenchmark<std::function<void()>>(state, FreeFunction);
77}
78BENCHMARK(BM_FunPtrStdFunction);
79
80void BM_FunPtrFunctionRef(benchmark::State& state) {
81 ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, FreeFunction);
82}
83BENCHMARK(BM_FunPtrFunctionRef);
84
85// Doesn't include construction or copy overhead in the loop.
86template <typename Function, typename Callable, typename... Args>
87void 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
96struct FunctorWithTrivialArgs {
97 void operator()(int a, int b, int c) const {
98 benchmark::DoNotOptimize(a);
99 benchmark::DoNotOptimize(b);
100 benchmark::DoNotOptimize(c);
101 }
102};
103
104void BM_TrivialArgsStdFunction(benchmark::State& state) {
105 CallFunctionBenchmark<std::function<void(int, int, int)>>(
106 state, FunctorWithTrivialArgs{}, 1, 2, 3);
107}
108BENCHMARK(BM_TrivialArgsStdFunction);
109
110void BM_TrivialArgsFunctionRef(benchmark::State& state) {
111 CallFunctionBenchmark<FunctionRef<void(int, int, int)>>(
112 state, FunctorWithTrivialArgs{}, 1, 2, 3);
113}
114BENCHMARK(BM_TrivialArgsFunctionRef);
115
116struct FunctorWithNonTrivialArgs {
117 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
124void 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}
130BENCHMARK(BM_NonTrivialArgsStdFunction);
131
132void 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}
138BENCHMARK(BM_NonTrivialArgsFunctionRef);
139
140} // namespace
141ABSL_NAMESPACE_END
142} // namespace absl