Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2012-2014 The Android Open Source Project
      3  *
      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
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     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.
     15  */
     16 
     17 #include <stdint.h>
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 #include <string.h>
     21 
     22 #include <vector>
     23 
     24 #ifndef BIONIC_BENCHMARK_H_
     25 #define BIONIC_BENCHMARK_H_
     26 
     27 namespace testing {
     28 
     29 class Benchmark;
     30 template <typename T> class BenchmarkWantsArg;
     31 template <typename T> class BenchmarkWithArg;
     32 
     33 void BenchmarkRegister(Benchmark* bm);
     34 int PrettyPrintInt(char* str, int len, unsigned int arg);
     35 
     36 class Benchmark {
     37  public:
     38   Benchmark(const char* name, void (*fn)(int)) : name_(strdup(name)), fn_(fn) {
     39     BenchmarkRegister(this);
     40   }
     41   Benchmark(const char* name) : name_(strdup(name)), fn_(NULL) {}
     42 
     43   virtual ~Benchmark() {
     44     free(name_);
     45   }
     46 
     47   const char* Name() { return name_; }
     48   virtual const char* ArgName() { return NULL; }
     49   virtual void RunFn(int iterations) { fn_(iterations); }
     50 
     51  protected:
     52   char* name_;
     53 
     54  private:
     55   void (*fn_)(int);
     56 };
     57 
     58 template <typename T>
     59 class BenchmarkWantsArgBase : public Benchmark {
     60  public:
     61   BenchmarkWantsArgBase(const char* name, void (*fn)(int, T)) : Benchmark(name) {
     62     fn_arg_ = fn;
     63   }
     64 
     65   BenchmarkWantsArgBase<T>* Arg(const char* arg_name, T arg) {
     66     BenchmarkRegister(new BenchmarkWithArg<T>(name_, fn_arg_, arg_name, arg));
     67     return this;
     68   }
     69 
     70  protected:
     71   virtual void RunFn(int) { printf("can't run arg benchmark %s without arg\n", Name()); }
     72   void (*fn_arg_)(int, T);
     73 };
     74 
     75 template <typename T>
     76 class BenchmarkWithArg : public BenchmarkWantsArg<T> {
     77  public:
     78   BenchmarkWithArg(const char* name, void (*fn)(int, T), const char* arg_name, T arg) :
     79       BenchmarkWantsArg<T>(name, fn), arg_(arg) {
     80     arg_name_ = strdup(arg_name);
     81   }
     82 
     83   virtual ~BenchmarkWithArg() {
     84     free(arg_name_);
     85   }
     86 
     87   virtual const char* ArgName() { return arg_name_; }
     88 
     89  protected:
     90   virtual void RunFn(int iterations) { BenchmarkWantsArg<T>::fn_arg_(iterations, arg_); }
     91 
     92  private:
     93   T arg_;
     94   char* arg_name_;
     95 };
     96 
     97 template <typename T>
     98 class BenchmarkWantsArg : public BenchmarkWantsArgBase<T> {
     99  public:
    100   BenchmarkWantsArg<T>(const char* name, void (*fn)(int, T)) :
    101     BenchmarkWantsArgBase<T>(name, fn) { }
    102 };
    103 
    104 template <>
    105 class BenchmarkWantsArg<int> : public BenchmarkWantsArgBase<int> {
    106  public:
    107   BenchmarkWantsArg<int>(const char* name, void (*fn)(int, int)) :
    108     BenchmarkWantsArgBase<int>(name, fn) { }
    109 
    110   BenchmarkWantsArg<int>* Arg(int arg) {
    111     char arg_name[100];
    112     PrettyPrintInt(arg_name, sizeof(arg_name), arg);
    113     BenchmarkRegister(new BenchmarkWithArg<int>(name_, fn_arg_, arg_name, arg));
    114     return this;
    115   }
    116 };
    117 
    118 static inline Benchmark* BenchmarkFactory(const char* name, void (*fn)(int)) {
    119   return new Benchmark(name, fn);
    120 }
    121 
    122 template <typename T>
    123 static inline BenchmarkWantsArg<T>* BenchmarkFactory(const char* name, void (*fn)(int, T)) {
    124   return new BenchmarkWantsArg<T>(name, fn);
    125 }
    126 
    127 }  // namespace testing
    128 
    129 template <typename T>
    130 static inline void BenchmarkAddArg(::testing::Benchmark* b, const char* name, T arg) {
    131   ::testing::BenchmarkWantsArg<T>* ba;
    132   ba = static_cast< ::testing::BenchmarkWantsArg<T>* >(b);
    133   ba->Arg(name, arg);
    134 }
    135 
    136 void SetBenchmarkBytesProcessed(uint64_t);
    137 void ResetBenchmarkTiming(void);
    138 void StopBenchmarkTiming(void);
    139 void StartBenchmarkTiming(void);
    140 void StartBenchmarkTiming(uint64_t);
    141 void StopBenchmarkTiming(uint64_t);
    142 
    143 #define BENCHMARK(f) \
    144     static ::testing::Benchmark* _benchmark_##f __attribute__((unused)) = \
    145         (::testing::Benchmark*)::testing::BenchmarkFactory(#f, f)
    146 
    147 #endif // BIONIC_BENCHMARK_H_
    148