Skip to content

Commit 6ec4255

Browse files
committed
bench: replace wall-clock timers with cpu-timers where possible
This commit improves the reliability of benchmarks by removing some of the influence of other background running processes. This is achieved by using CPU bound clocks that aren't influenced by interrupts, sleeps, blocked I/O, etc.
1 parent b9313c6 commit 6ec4255

File tree

4 files changed

+42
-21
lines changed

4 files changed

+42
-21
lines changed

src/bench.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
55
***********************************************************************/
66

7+
#define _POSIX_C_SOURCE 200112L /* for clock_gettime() */
8+
79
#include <stdio.h>
810
#include <stdlib.h>
911
#include <string.h>

src/bench.h

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,30 +7,44 @@
77
#ifndef SECP256K1_BENCH_H
88
#define SECP256K1_BENCH_H
99

10+
#if defined(_WIN32)
11+
# include <windows.h>
12+
#else /* POSIX */
13+
# include <time.h>
14+
#endif
15+
1016
#include <stdlib.h>
1117
#include <stdint.h>
1218
#include <stdio.h>
1319
#include <string.h>
1420

15-
#if (defined(_MSC_VER) && _MSC_VER >= 1900)
16-
# include <time.h>
17-
#else
18-
# include <sys/time.h>
19-
#endif
21+
static int64_t gettime_us(void) {
22+
#if defined(_WIN32)
23+
24+
LARGE_INTEGER freq, counter;
25+
QueryPerformanceFrequency(&freq);
26+
QueryPerformanceCounter(&counter);
27+
return (int64_t)(counter.QuadPart * 1000000 / freq.QuadPart);
28+
29+
#else /* POSIX */
30+
31+
# if defined(CLOCK_PROCESS_CPUTIME_ID)
32+
/* In theory, CLOCK_PROCESS_CPUTIME_ID is only useful if the process is locked to a core,
33+
* see `man clock_gettime` on Linux. In practice, modern CPUs have synchronized TSCs which
34+
* address this issue, see https://docs.amd.com/r/en-US/ug1586-onload-user/Timer-TSC-Stability . */
35+
const clockid_t clock_type = CLOCK_PROCESS_CPUTIME_ID;
36+
# elif defined(CLOCK_MONOTONIC)
37+
/* fallback to wall-clock timer */
38+
const clockid_t clock_type = CLOCK_MONOTONIC;
39+
# else
40+
/* fallback to less precise wall-clock timer */
41+
const clockid_t clock_type = CLOCK_REALTIME;
42+
# endif
43+
44+
struct timespec ts;
45+
clock_gettime(clock_type, &ts);
46+
return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
2047

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(EXIT_FAILURE);
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;
3448
#endif
3549
}
3650

@@ -105,9 +119,9 @@ static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setu
105119
if (setup != NULL) {
106120
setup(data);
107121
}
108-
begin = gettime_i64();
122+
begin = gettime_us();
109123
benchmark(data, iter);
110-
total = gettime_i64() - begin;
124+
total = gettime_us() - begin;
111125
if (teardown != NULL) {
112126
teardown(data, iter);
113127
}

src/bench_ecmult.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
* Distributed under the MIT software license, see the accompanying *
44
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
55
***********************************************************************/
6+
7+
#define _POSIX_C_SOURCE 200112L /* for clock_gettime() */
8+
69
#include <stdio.h>
710
#include <stdlib.h>
811

@@ -362,7 +365,6 @@ int main(int argc, char **argv) {
362365
}
363366
secp256k1_ge_set_all_gej_var(data.pubkeys, data.pubkeys_gej, POINTS);
364367

365-
366368
print_output_table_header_row();
367369
/* Initialize offset1 and offset2 */
368370
hash_into_offset(&data, 0);

src/bench_internal.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
* Distributed under the MIT software license, see the accompanying *
44
* file COPYING or https://www.opensource.org/licenses/mit-license.php.*
55
***********************************************************************/
6+
7+
#define _POSIX_C_SOURCE 200112L /* for clock_gettime() */
8+
69
#include <stdio.h>
710
#include <stdlib.h>
811

0 commit comments

Comments
 (0)