benchmark_main.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 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 #include "benchmark.h"
17 #include <regex.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <string>
22 #include <inttypes.h>
23 #include <time.h>
24 #include <map>
25 
29 typedef std::map<std::string, ::testing::Benchmark*> BenchmarkMap;
30 typedef BenchmarkMap::iterator BenchmarkMapIt;
31 
33  static BenchmarkMap g_benchmarks;
34  return g_benchmarks;
35 }
36 
37 static int g_name_column_width = 20;
38 
39 static int Round(int n) {
40  int base = 1;
41  while (base*10 < n) {
42  base *= 10;
43  }
44  if (n < 2*base) {
45  return 2*base;
46  }
47  if (n < 5*base) {
48  return 5*base;
49  }
50  return 10*base;
51 }
52 
53 #ifdef __APPLE__
54  #include <mach/mach_time.h>
55  static mach_timebase_info_data_t g_time_info;
56  static void __attribute__((constructor)) init_info() {
57  mach_timebase_info(&g_time_info);
58  }
59 #endif
60 
61 static int64_t NanoTime() {
62 #if defined(__APPLE__)
63  uint64_t t = mach_absolute_time();
64  return t * g_time_info.numer / g_time_info.denom;
65 #else
66  struct timespec t;
67  t.tv_sec = t.tv_nsec = 0;
68  clock_gettime(CLOCK_MONOTONIC, &t);
69  return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
70 #endif
71 }
72 
73 namespace testing {
75  args_.push_back(arg);
76  return this;
77 }
78 
79 Benchmark* Benchmark::Range(int lo, int hi) {
80  const int kRangeMultiplier = 8;
81  if (hi < lo) {
82  int temp = hi;
83  hi = lo;
84  lo = temp;
85  }
86  while (lo < hi) {
87  args_.push_back(lo);
88  lo *= kRangeMultiplier;
89  }
90  // We always run the hi number.
91  args_.push_back(hi);
92  return this;
93 }
94 
95 const char* Benchmark::Name() {
96  return name_;
97 }
98 bool Benchmark::ShouldRun(int argc, char* argv[]) {
99  if (argc == 1) {
100  return true; // With no arguments, we run all benchmarks.
101  }
102  // Otherwise, we interpret each argument as a regular expression and
103  // see if any of our benchmarks match.
104  for (int i = 1; i < argc; i++) {
105  regex_t re;
106  if (regcomp(&re, argv[i], 0) != 0) {
107  fprintf(stderr, "couldn't compile \"%s\" as a regular expression!\n", argv[i]);
108  exit(EXIT_FAILURE);
109  }
110  int match = regexec(&re, name_, 0, NULL, 0);
111  regfree(&re);
112  if (match != REG_NOMATCH) {
113  return true;
114  }
115  }
116  return false;
117 }
118 void Benchmark::Register(const char* name, void (*fn)(int), void (*fn_range)(int, int)) {
119  name_ = name;
120  fn_ = fn;
121  fn_range_ = fn_range;
122  if (fn_ == NULL && fn_range_ == NULL) {
123  fprintf(stderr, "%s: missing function\n", name_);
124  exit(EXIT_FAILURE);
125  }
126  gBenchmarks().insert(std::make_pair(name, this));
127 }
129  if (fn_ != NULL) {
130  RunWithArg(0);
131  } else {
132  if (args_.empty()) {
133  fprintf(stderr, "%s: no args!\n", name_);
134  exit(EXIT_FAILURE);
135  }
136  for (size_t i = 0; i < args_.size(); ++i) {
137  RunWithArg(args_[i]);
138  }
139  }
140 }
141 void Benchmark::RunRepeatedlyWithArg(int iterations, int arg) {
142  g_flops_processed = 0;
145  if (fn_ != NULL) {
146  fn_(iterations);
147  } else {
148  fn_range_(iterations, arg);
149  }
150  if (g_benchmark_start_time_ns != 0) {
152  }
153 }
155  // run once in case it's expensive
156  int iterations = 1;
157  RunRepeatedlyWithArg(iterations, arg);
158  while (g_benchmark_total_time_ns < 1e9 && iterations < 1e9) {
159  int last = iterations;
160  if (g_benchmark_total_time_ns/iterations == 0) {
161  iterations = 1e9;
162  } else {
163  iterations = 1e9 / (g_benchmark_total_time_ns/iterations);
164  }
165  iterations = std::max(last + 1, std::min(iterations + iterations/2, 100*last));
166  iterations = Round(iterations);
167  RunRepeatedlyWithArg(iterations, arg);
168  }
169  char throughput[100];
170  throughput[0] = '\0';
172  double mflops_processed = static_cast<double>(g_flops_processed)/1e6;
173  double seconds = static_cast<double>(g_benchmark_total_time_ns)/1e9;
174  snprintf(throughput, sizeof(throughput), " %8.2f MFlops/s", mflops_processed/seconds);
175  }
176  char full_name[100];
177  if (fn_range_ != NULL) {
178  if (arg >= (1<<20)) {
179  snprintf(full_name, sizeof(full_name), "%s/%dM", name_, arg/(1<<20));
180  } else if (arg >= (1<<10)) {
181  snprintf(full_name, sizeof(full_name), "%s/%dK", name_, arg/(1<<10));
182  } else {
183  snprintf(full_name, sizeof(full_name), "%s/%d", name_, arg);
184  }
185  } else {
186  snprintf(full_name, sizeof(full_name), "%s", name_);
187  }
188  printf("%-*s %10d %10" PRId64 "%s\n", g_name_column_width, full_name,
189  iterations, g_benchmark_total_time_ns/iterations, throughput);
190  fflush(stdout);
191 }
192 } // namespace testing
195 }
197  if (g_benchmark_start_time_ns != 0) {
199  }
201 }
203  if (g_benchmark_start_time_ns == 0) {
205  }
206 }
207 int main(int argc, char* argv[]) {
208  if (gBenchmarks().empty()) {
209  fprintf(stderr, "No benchmarks registered!\n");
210  exit(EXIT_FAILURE);
211  }
212  for (BenchmarkMapIt it = gBenchmarks().begin(); it != gBenchmarks().end(); ++it) {
213  int name_width = static_cast<int>(strlen(it->second->Name()));
215  }
216  bool need_header = true;
217  for (BenchmarkMapIt it = gBenchmarks().begin(); it != gBenchmarks().end(); ++it) {
218  ::testing::Benchmark* b = it->second;
219  if (b->ShouldRun(argc, argv)) {
220  if (need_header) {
221  printf("%-*s %10s %10s\n", g_name_column_width, "", "iterations", "ns/op");
222  fflush(stdout);
223  need_header = false;
224  }
225  b->Run();
226  }
227  }
228  if (need_header) {
229  fprintf(stderr, "No matching benchmarks!\n");
230  fprintf(stderr, "Available benchmarks:\n");
231  for (BenchmarkMapIt it = gBenchmarks().begin(); it != gBenchmarks().end(); ++it) {
232  fprintf(stderr, " %s\n", it->second->Name());
233  }
234  exit(EXIT_FAILURE);
235  }
236  return 0;
237 }
void regfree(regex_t *__preg)
void StopBenchmarkTiming()
#define max(a, b)
Definition: datatypes.h:20
constexpr int last(int, int result)
Scalar * b
Definition: benchVecAdd.cpp:17
Benchmark * Arg(int x)
#define min(a, b)
Definition: datatypes.h:19
int n
void RunWithArg(int arg)
static int Round(int n)
void(* fn_range_)(int, int)
Definition: benchmark.h:37
Definition: cast.h:1853
bool ShouldRun(int argc, char *argv[])
void StartBenchmarkTiming()
void(* fn_)(int)
Definition: benchmark.h:36
#define PRId64
Definition: ms_inttypes.h:76
const char * Name()
static int g_name_column_width
static int64_t g_flops_processed
void SetBenchmarkFlopsProcessed(int64_t x)
void Register(const char *name, void(*fn)(int), void(*fn_range)(int, int))
int regexec(const regex_t *__restrict __preg, const char *__restrict __string, size_t __nmatch, regmatch_t __pmatch[__restrict_arr], int __eflags)
signed __int64 int64_t
Definition: ms_stdint.h:94
unsigned __int64 uint64_t
Definition: ms_stdint.h:95
std::map< std::string,::testing::Benchmark * > BenchmarkMap
void RunRepeatedlyWithArg(int iterations, int arg)
int regcomp(regex_t *__restrict __preg, const char *__restrict __pattern, int __cflags)
static int64_t g_benchmark_total_time_ns
std::vector< int > args_
Definition: benchmark.h:38
#define NULL
Definition: ccolamd.c:609
int main(int argc, char *argv[])
Benchmark * Range(int lo, int hi)
BenchmarkMap & gBenchmarks()
BenchmarkMap::iterator BenchmarkMapIt
const char * name_
Definition: benchmark.h:35
Annotation for function names.
Definition: attr.h:36
Annotation indicating that a class derives from another given type.
Definition: attr.h:42
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
Point2 t(10, 10)
static int64_t NanoTime()
__attribute__((noinline)) void bench_reverse(const MatrixType &m)
static int64_t g_benchmark_start_time_ns


gtsam
Author(s):
autogenerated on Sat May 8 2021 02:41:42