/* * Copyright (C) 2012-2014 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 #include #include #include #include #ifndef BIONIC_BENCHMARK_H_ #define BIONIC_BENCHMARK_H_ namespace testing { class Benchmark; template class BenchmarkWantsArg; template class BenchmarkWithArg; void BenchmarkRegister(Benchmark* bm); int PrettyPrintInt(char* str, int len, unsigned int arg); class Benchmark { public: Benchmark(const char* name, void (*fn)(int)) : name_(strdup(name)), fn_(fn) { BenchmarkRegister(this); } Benchmark(const char* name) : name_(strdup(name)), fn_(NULL) {} virtual ~Benchmark() { free(name_); } const char* Name() { return name_; } virtual const char* ArgName() { return NULL; } virtual void RunFn(int iterations) { fn_(iterations); } protected: char* name_; private: void (*fn_)(int); }; template class BenchmarkWantsArgBase : public Benchmark { public: BenchmarkWantsArgBase(const char* name, void (*fn)(int, T)) : Benchmark(name) { fn_arg_ = fn; } BenchmarkWantsArgBase* Arg(const char* arg_name, T arg) { BenchmarkRegister(new BenchmarkWithArg(name_, fn_arg_, arg_name, arg)); return this; } protected: virtual void RunFn(int) { printf("can't run arg benchmark %s without arg\n", Name()); } void (*fn_arg_)(int, T); }; template class BenchmarkWithArg : public BenchmarkWantsArg { public: BenchmarkWithArg(const char* name, void (*fn)(int, T), const char* arg_name, T arg) : BenchmarkWantsArg(name, fn), arg_(arg) { arg_name_ = strdup(arg_name); } virtual ~BenchmarkWithArg() { free(arg_name_); } virtual const char* ArgName() { return arg_name_; } protected: virtual void RunFn(int iterations) { BenchmarkWantsArg::fn_arg_(iterations, arg_); } private: T arg_; char* arg_name_; }; template class BenchmarkWantsArg : public BenchmarkWantsArgBase { public: BenchmarkWantsArg(const char* name, void (*fn)(int, T)) : BenchmarkWantsArgBase(name, fn) { } }; template <> class BenchmarkWantsArg : public BenchmarkWantsArgBase { public: BenchmarkWantsArg(const char* name, void (*fn)(int, int)) : BenchmarkWantsArgBase(name, fn) { } BenchmarkWantsArg* Arg(int arg) { char arg_name[100]; PrettyPrintInt(arg_name, sizeof(arg_name), arg); BenchmarkRegister(new BenchmarkWithArg(name_, fn_arg_, arg_name, arg)); return this; } }; static inline Benchmark* BenchmarkFactory(const char* name, void (*fn)(int)) { return new Benchmark(name, fn); } template static inline BenchmarkWantsArg* BenchmarkFactory(const char* name, void (*fn)(int, T)) { return new BenchmarkWantsArg(name, fn); } } // namespace testing template static inline void BenchmarkAddArg(::testing::Benchmark* b, const char* name, T arg) { ::testing::BenchmarkWantsArg* ba; ba = static_cast< ::testing::BenchmarkWantsArg* >(b); ba->Arg(name, arg); } void SetBenchmarkBytesProcessed(uint64_t); void ResetBenchmarkTiming(void); void StopBenchmarkTiming(void); void StartBenchmarkTiming(void); void StartBenchmarkTiming(uint64_t); void StopBenchmarkTiming(uint64_t); #define BENCHMARK(f) \ static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \ (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f) #endif // BIONIC_BENCHMARK_H_