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