2 * Copyright 2012 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/test/function_benchmark/benchmark_impl.h"
18 #include "folly/test/function_benchmark/test_functions.h"
20 #include "folly/Benchmark.h"
21 #include "folly/ScopeGuard.h"
22 #include <gflags/gflags.h>
23 #include <glog/logging.h>
25 using folly::ScopeGuard;
26 using folly::makeGuard;
28 // Declare the bm_max_iters flag from folly/Benchmark.cpp
29 DECLARE_int32(bm_max_iters);
31 // Directly invoking a function
32 BENCHMARK(fn_invoke, iters) {
33 for (int n = 0; n < iters; ++n) {
38 // Invoking a function through a function pointer
39 BENCHMARK(fn_ptr_invoke, iters) {
40 BM_fn_ptr_invoke_impl(iters, doNothing);
43 // Invoking a function through a std::function object
44 BENCHMARK(std_function_invoke, iters) {
45 BM_std_function_invoke_impl(iters, doNothing);
48 // Invoking a member function through a member function pointer
49 BENCHMARK(mem_fn_invoke, iters) {
51 BM_mem_fn_invoke_impl(iters, &tc, &TestClass::doNothing);
54 // Invoke a function pointer through an inlined wrapper function
55 BENCHMARK(fn_ptr_invoke_through_inline, iters) {
56 BM_fn_ptr_invoke_inlined_impl(iters, doNothing);
59 // Invoke a lambda that calls doNothing() through an inlined wrapper function
60 BENCHMARK(lambda_invoke_fn, iters) {
61 BM_invoke_fn_template_impl(iters, [] { doNothing(); });
64 // Invoke a lambda that does nothing
65 BENCHMARK(lambda_noop, iters) {
66 BM_invoke_fn_template_impl(iters, [] {});
69 // Invoke a lambda that modifies a local variable
70 BENCHMARK(lambda_local_var, iters) {
73 BM_invoke_fn_template_impl(iters, [&] {
74 // Do something slightly more complicated than just incrementing a
75 // variable. Otherwise gcc is smart enough to optimize the loop away.
82 // Use the values we computed, so gcc won't optimize the loop away
83 CHECK_EQ(iters, count1);
84 CHECK_EQ(iters / 2, count2);
87 // Invoke a function pointer through the same wrapper used for lambdas
88 BENCHMARK(fn_ptr_invoke_through_template, iters) {
89 BM_invoke_fn_template_impl(iters, doNothing);
92 // Invoking a virtual method
93 BENCHMARK(virtual_fn_invoke, iters) {
95 BM_virtual_fn_invoke_impl(iters, &vc);
98 // Creating a function pointer and invoking it
99 BENCHMARK(fn_ptr_create_invoke, iters) {
100 for (int n = 0; n < iters; ++n) {
101 void (*fn)() = doNothing;
106 // Creating a std::function object from a function pointer, and invoking it
107 BENCHMARK(std_function_create_invoke, iters) {
108 for (int n = 0; n < iters; ++n) {
109 std::function<void()> fn = doNothing;
114 // Creating a pointer-to-member and invoking it
115 BENCHMARK(mem_fn_create_invoke, iters) {
117 for (int n = 0; n < iters; ++n) {
118 void (TestClass::*memfn)() = &TestClass::doNothing;
123 // Using std::bind to create a std::function from a member function,
125 BENCHMARK(std_bind_create_invoke, iters) {
127 for (int n = 0; n < iters; ++n) {
128 std::function<void()> fn = std::bind(&TestClass::doNothing, &tc);
133 // Using ScopeGuard to invoke a std::function
134 BENCHMARK(scope_guard_std_function, iters) {
135 std::function<void()> fn(doNothing);
136 for (int n = 0; n < iters; ++n) {
137 ScopeGuard g = makeGuard(fn);
141 // Using ScopeGuard to invoke a std::function,
142 // but create the ScopeGuard with an rvalue to a std::function
143 BENCHMARK(scope_guard_std_function_rvalue, iters) {
144 for (int n = 0; n < iters; ++n) {
145 ScopeGuard g = makeGuard(std::function<void()>(doNothing));
149 // Using ScopeGuard to invoke a function pointer
150 BENCHMARK(scope_guard_fn_ptr, iters) {
151 for (int n = 0; n < iters; ++n) {
152 ScopeGuard g = makeGuard(doNothing);
156 // Using ScopeGuard to invoke a lambda that does nothing
157 BENCHMARK(scope_guard_lambda_noop, iters) {
158 for (int n = 0; n < iters; ++n) {
159 ScopeGuard g = makeGuard([] {});
163 // Using ScopeGuard to invoke a lambda that invokes a function
164 BENCHMARK(scope_guard_lambda_function, iters) {
165 for (int n = 0; n < iters; ++n) {
166 ScopeGuard g = makeGuard([] { doNothing(); });
170 // Using ScopeGuard to invoke a lambda that modifies a local variable
171 BENCHMARK(scope_guard_lambda_local_var, iters) {
173 for (int n = 0; n < iters; ++n) {
174 ScopeGuard g = makeGuard([&] {
175 // Increment count if n is odd. Without this conditional check
176 // (i.e., if we just increment count each time through the loop),
177 // gcc is smart enough to optimize the entire loop away, and just set
185 // Check that the value of count is what we expect.
186 // This check is necessary: if we don't use count, gcc detects that count is
187 // unused and optimizes the entire loop away.
188 CHECK_EQ(iters / 2, count);
193 int main(int argc, char** argv) {
194 google::ParseCommandLineFlags(&argc, &argv, true);
195 folly::runBenchmarks();