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