Bitcoin Core  27.99.0
P2P Digital Currency
bench.h
Go to the documentation of this file.
1 /***********************************************************************
2  * Copyright (c) 2014 Pieter Wuille *
3  * Distributed under the MIT software license, see the accompanying *
4  * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
5  ***********************************************************************/
6 
7 #ifndef SECP256K1_BENCH_H
8 #define SECP256K1_BENCH_H
9 
10 #include <stdlib.h>
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <string.h>
14 
15 #if (defined(_MSC_VER) && _MSC_VER >= 1900)
16 # include <time.h>
17 #else
18 # include <sys/time.h>
19 #endif
20 
21 static int64_t gettime_i64(void) {
22 #if (defined(_MSC_VER) && _MSC_VER >= 1900)
23  /* C11 way to get wallclock time */
24  struct timespec tv;
25  if (!timespec_get(&tv, TIME_UTC)) {
26  fputs("timespec_get failed!", stderr);
27  exit(1);
28  }
29  return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL;
30 #else
31  struct timeval tv;
32  gettimeofday(&tv, NULL);
33  return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL;
34 #endif
35 }
36 
37 #define FP_EXP (6)
38 #define FP_MULT (1000000LL)
39 
40 /* Format fixed point number. */
41 static void print_number(const int64_t x) {
42  int64_t x_abs, y;
43  int c, i, rounding, g; /* g = integer part size, c = fractional part size */
44  size_t ptr;
45  char buffer[30];
46 
47  if (x == INT64_MIN) {
48  /* Prevent UB. */
49  printf("ERR");
50  return;
51  }
52  x_abs = x < 0 ? -x : x;
53 
54  /* Determine how many decimals we want to show (more than FP_EXP makes no
55  * sense). */
56  y = x_abs;
57  c = 0;
58  while (y > 0LL && y < 100LL * FP_MULT && c < FP_EXP) {
59  y *= 10LL;
60  c++;
61  }
62 
63  /* Round to 'c' decimals. */
64  y = x_abs;
65  rounding = 0;
66  for (i = c; i < FP_EXP; ++i) {
67  rounding = (y % 10) >= 5;
68  y /= 10;
69  }
70  y += rounding;
71 
72  /* Format and print the number. */
73  ptr = sizeof(buffer) - 1;
74  buffer[ptr] = 0;
75  g = 0;
76  if (c != 0) { /* non zero fractional part */
77  for (i = 0; i < c; ++i) {
78  buffer[--ptr] = '0' + (y % 10);
79  y /= 10;
80  }
81  } else if (c == 0) { /* fractional part is 0 */
82  buffer[--ptr] = '0';
83  }
84  buffer[--ptr] = '.';
85  do {
86  buffer[--ptr] = '0' + (y % 10);
87  y /= 10;
88  g++;
89  } while (y != 0);
90  if (x < 0) {
91  buffer[--ptr] = '-';
92  g++;
93  }
94  printf("%5.*s", g, &buffer[ptr]); /* Prints integer part */
95  printf("%-*s", FP_EXP, &buffer[ptr + g]); /* Prints fractional part */
96 }
97 
98 static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) {
99  int i;
100  int64_t min = INT64_MAX;
101  int64_t sum = 0;
102  int64_t max = 0;
103  for (i = 0; i < count; i++) {
104  int64_t begin, total;
105  if (setup != NULL) {
106  setup(data);
107  }
108  begin = gettime_i64();
109  benchmark(data, iter);
110  total = gettime_i64() - begin;
111  if (teardown != NULL) {
112  teardown(data, iter);
113  }
114  if (total < min) {
115  min = total;
116  }
117  if (total > max) {
118  max = total;
119  }
120  sum += total;
121  }
122  /* ',' is used as a column delimiter */
123  printf("%-30s, ", name);
124  print_number(min * FP_MULT / iter);
125  printf(" , ");
126  print_number(((sum * FP_MULT) / count) / iter);
127  printf(" , ");
128  print_number(max * FP_MULT / iter);
129  printf("\n");
130 }
131 
132 static int have_flag(int argc, char** argv, char *flag) {
133  char** argm = argv + argc;
134  argv++;
135  while (argv != argm) {
136  if (strcmp(*argv, flag) == 0) {
137  return 1;
138  }
139  argv++;
140  }
141  return 0;
142 }
143 
144 /* takes an array containing the arguments that the user is allowed to enter on the command-line
145  returns:
146  - 1 if the user entered an invalid argument
147  - 0 if all the user entered arguments are valid */
148 static int have_invalid_args(int argc, char** argv, char** valid_args, size_t n) {
149  size_t i;
150  int found_valid;
151  char** argm = argv + argc;
152  argv++;
153 
154  while (argv != argm) {
155  found_valid = 0;
156  for (i = 0; i < n; i++) {
157  if (strcmp(*argv, valid_args[i]) == 0) {
158  found_valid = 1; /* user entered a valid arg from the list */
159  break;
160  }
161  }
162  if (found_valid == 0) {
163  return 1; /* invalid arg found */
164  }
165  argv++;
166  }
167  return 0;
168 }
169 
170 static int get_iters(int default_iters) {
171  char* env = getenv("SECP256K1_BENCH_ITERS");
172  if (env) {
173  return strtol(env, NULL, 0);
174  } else {
175  return default_iters;
176  }
177 }
178 
179 static void print_output_table_header_row(void) {
180  char* bench_str = "Benchmark"; /* left justified */
181  char* min_str = " Min(us) "; /* center alignment */
182  char* avg_str = " Avg(us) ";
183  char* max_str = " Max(us) ";
184  printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str);
185  printf("\n");
186 }
187 
188 #endif /* SECP256K1_BENCH_H */
volatile double sum
Definition: examples.cpp:10
void printf(const char *fmt, const Args &... args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1077
const char * name
Definition: rest.cpp:50
static int get_iters(int default_iters)
Definition: bench.h:170
#define FP_EXP
Definition: bench.h:37
static void print_output_table_header_row(void)
Definition: bench.h:179
static void print_number(const int64_t x)
Definition: bench.h:41
static int64_t gettime_i64(void)
Definition: bench.h:21
#define FP_MULT
Definition: bench.h:38
static void run_benchmark(char *name, void(*benchmark)(void *, int), void(*setup)(void *), void(*teardown)(void *, int), void *data, int count, int iter)
Definition: bench.h:98
static int have_invalid_args(int argc, char **argv, char **valid_args, size_t n)
Definition: bench.h:148
static int have_flag(int argc, char **argv, char *flag)
Definition: bench.h:132
static int count