Bitcoin Core 28.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
21static 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. */
41static 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
98static 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
132static 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 */
148static 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
170static 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
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(FormatStringCheck< sizeof...(Args)> fmt, const Args &... args)
Format list of arguments to std::cout, according to the given format string.
Definition: tinyformat.h:1089
const char * name
Definition: rest.cpp:49
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