| /* |
| * Copyright (C) 2022 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "android-base/function_ref.h" |
| |
| #include <benchmark/benchmark.h> |
| |
| #include <functional> |
| #include <utility> |
| |
| #include <time.h> |
| |
| using android::base::function_ref; |
| |
| template <class Callable, class... Args> |
| [[clang::noinline]] auto call(Callable&& c, Args&&... args) { |
| return c(std::forward<Args>(args)...); |
| } |
| |
| [[clang::noinline]] static int testFunc(int, const char*, char) { |
| return time(nullptr); |
| } |
| |
| using Func = decltype(testFunc); |
| |
| static void BenchmarkFuncRaw(benchmark::State& state) { |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call(testFunc, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkFuncRaw); |
| |
| static void BenchmarkFuncPtr(benchmark::State& state) { |
| auto ptr = &testFunc; |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call(ptr, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkFuncPtr); |
| |
| static void BenchmarkStdFunction(benchmark::State& state) { |
| std::function<Func> f(testFunc); |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call(f, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkStdFunction); |
| |
| static void BenchmarkFunctionRef(benchmark::State& state) { |
| function_ref<Func> f(testFunc); |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call(f, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkFunctionRef); |
| |
| namespace { |
| struct BigFunc { |
| char big[128]; |
| [[clang::noinline]] int operator()(int, const char*, char) const { return time(nullptr); } |
| }; |
| |
| static BigFunc bigFunc; |
| } // namespace |
| |
| static void BenchmarkBigRaw(benchmark::State& state) { |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call(bigFunc, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkBigRaw); |
| |
| static void BenchmarkBigStdFunction(benchmark::State& state) { |
| std::function<Func> f(bigFunc); |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call(f, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkBigStdFunction); |
| |
| static void BenchmarkBigFunctionRef(benchmark::State& state) { |
| function_ref<Func> f(bigFunc); |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call(f, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkBigFunctionRef); |
| |
| static void BenchmarkMakeFunctionRef(benchmark::State& state) { |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call<function_ref<Func>>(bigFunc, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkMakeFunctionRef); |
| |
| static void BenchmarkMakeStdFunction(benchmark::State& state) { |
| for (auto _ : state) { |
| benchmark::DoNotOptimize(call<std::function<Func>>(bigFunc, 1, "1", '1')); |
| } |
| } |
| BENCHMARK(BenchmarkMakeStdFunction); |