Mercurial > hg > CbC > CbC_llvm
diff libcxx/benchmarks/function.bench.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 1f2b6ac9f198 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcxx/benchmarks/function.bench.cpp Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,231 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include <cstdint> +#include <functional> +#include <memory> +#include <string> + +#include "CartesianBenchmarks.h" +#include "benchmark/benchmark.h" +#include "test_macros.h" + +namespace { + +enum class FunctionType { + Null, + FunctionPointer, + MemberFunctionPointer, + MemberPointer, + SmallTrivialFunctor, + SmallNonTrivialFunctor, + LargeTrivialFunctor, + LargeNonTrivialFunctor +}; + +struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> { + static constexpr const char* Names[] = {"Null", + "FuncPtr", + "MemFuncPtr", + "MemPtr", + "SmallTrivialFunctor", + "SmallNonTrivialFunctor", + "LargeTrivialFunctor", + "LargeNonTrivialFunctor"}; +}; + +enum class Opacity { kOpaque, kTransparent }; + +struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> { + static constexpr const char* Names[] = {"Opaque", "Transparent"}; +}; + +struct S { + int function() const { return 0; } + int field = 0; +}; + +int FunctionWithS(const S*) { return 0; } + +struct SmallTrivialFunctor { + int operator()(const S*) const { return 0; } +}; +struct SmallNonTrivialFunctor { + SmallNonTrivialFunctor() {} + SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {} + ~SmallNonTrivialFunctor() {} + int operator()(const S*) const { return 0; } +}; +struct LargeTrivialFunctor { + LargeTrivialFunctor() { + // Do not spend time initializing the padding. + } + int padding[16]; + int operator()(const S*) const { return 0; } +}; +struct LargeNonTrivialFunctor { + int padding[16]; + LargeNonTrivialFunctor() { + // Do not spend time initializing the padding. + } + LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {} + ~LargeNonTrivialFunctor() {} + int operator()(const S*) const { return 0; } +}; + +using Function = std::function<int(const S*)>; + +TEST_ALWAYS_INLINE +inline Function MakeFunction(FunctionType type, bool opaque = false) { + switch (type) { + case FunctionType::Null: + return nullptr; + case FunctionType::FunctionPointer: + return maybeOpaque(FunctionWithS, opaque); + case FunctionType::MemberFunctionPointer: + return maybeOpaque(&S::function, opaque); + case FunctionType::MemberPointer: + return maybeOpaque(&S::field, opaque); + case FunctionType::SmallTrivialFunctor: + return maybeOpaque(SmallTrivialFunctor{}, opaque); + case FunctionType::SmallNonTrivialFunctor: + return maybeOpaque(SmallNonTrivialFunctor{}, opaque); + case FunctionType::LargeTrivialFunctor: + return maybeOpaque(LargeTrivialFunctor{}, opaque); + case FunctionType::LargeNonTrivialFunctor: + return maybeOpaque(LargeNonTrivialFunctor{}, opaque); + } +} + +template <class Opacity, class FunctionType> +struct ConstructAndDestroy { + static void run(benchmark::State& state) { + for (auto _ : state) { + if (Opacity() == ::Opacity::kOpaque) { + benchmark::DoNotOptimize(MakeFunction(FunctionType(), true)); + } else { + MakeFunction(FunctionType()); + } + } + } + + static std::string name() { + return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name(); + } +}; + +template <class FunctionType> +struct Copy { + static void run(benchmark::State& state) { + auto value = MakeFunction(FunctionType()); + for (auto _ : state) { + benchmark::DoNotOptimize(value); + auto copy = value; // NOLINT + benchmark::DoNotOptimize(copy); + } + } + + static std::string name() { return "BM_Copy" + FunctionType::name(); } +}; + +template <class FunctionType> +struct Move { + static void run(benchmark::State& state) { + Function values[2] = {MakeFunction(FunctionType())}; + int i = 0; + for (auto _ : state) { + benchmark::DoNotOptimize(values); + benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i])); + i ^= 1; + } + } + + static std::string name() { + return "BM_Move" + FunctionType::name(); + } +}; + +template <class Function1, class Function2> +struct Swap { + static void run(benchmark::State& state) { + Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())}; + for (auto _ : state) { + benchmark::DoNotOptimize(values); + values[0].swap(values[1]); + } + } + + static bool skip() { return Function1() > Function2(); } + + static std::string name() { + return "BM_Swap" + Function1::name() + Function2::name(); + } +}; + +template <class FunctionType> +struct OperatorBool { + static void run(benchmark::State& state) { + auto f = MakeFunction(FunctionType()); + for (auto _ : state) { + benchmark::DoNotOptimize(f); + benchmark::DoNotOptimize(static_cast<bool>(f)); + } + } + + static std::string name() { return "BM_OperatorBool" + FunctionType::name(); } +}; + +template <class FunctionType> +struct Invoke { + static void run(benchmark::State& state) { + S s; + const auto value = MakeFunction(FunctionType()); + for (auto _ : state) { + benchmark::DoNotOptimize(value); + benchmark::DoNotOptimize(value(&s)); + } + } + + static bool skip() { return FunctionType() == ::FunctionType::Null; } + + static std::string name() { return "BM_Invoke" + FunctionType::name(); } +}; + +template <class FunctionType> +struct InvokeInlined { + static void run(benchmark::State& state) { + S s; + for (auto _ : state) { + MakeFunction(FunctionType())(&s); + } + } + + static bool skip() { return FunctionType() == ::FunctionType::Null; } + + static std::string name() { + return "BM_InvokeInlined" + FunctionType::name(); + } +}; + +} // namespace + +int main(int argc, char** argv) { + benchmark::Initialize(&argc, argv); + if (benchmark::ReportUnrecognizedArguments(argc, argv)) + return 1; + + makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity, + AllFunctionTypes>(); + makeCartesianProductBenchmark<Copy, AllFunctionTypes>(); + makeCartesianProductBenchmark<Move, AllFunctionTypes>(); + makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>(); + makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>(); + makeCartesianProductBenchmark<Invoke, AllFunctionTypes>(); + makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>(); + benchmark::RunSpecifiedBenchmarks(); +}