Skip to content

Commit ef9e40e

Browse files
committed
Add more precise clocks
1 parent abf4566 commit ef9e40e

File tree

3 files changed

+55
-18
lines changed

3 files changed

+55
-18
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
3030
#=============================
3131
set(CMAKE_C_STANDARD 90)
3232
set(CMAKE_C_EXTENSIONS OFF)
33+
# Enable POSIX features while maintaining ISO C compliance
34+
add_compile_definitions(_POSIX_C_SOURCE=200112L) #needed for `clock_gettime()` in bench.c
3335

3436
#=============================
3537
# Configurable options

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ Benchmark
159159
------------
160160
If configured with `--enable-benchmark` (which is the default), binaries for benchmarking the libsecp256k1 functions will be present in the root directory after the build.
161161
162+
For an accurate benchmark, it is strongly recommended to pin the process to a dedicated CPU core and to disable CPU frequency scaling.
163+
162164
To print the benchmark result to the command line:
163165
164166
$ ./bench_name

src/bench.h

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

10+
#if defined(_WIN32)
11+
# include <windows.h>
12+
#else
13+
# include <time.h>
14+
# include <sys/time.h>
15+
#endif
16+
1017
#include <stdlib.h>
1118
#include <stdint.h>
1219
#include <stdio.h>
1320
#include <string.h>
1421

15-
#if (defined(_MSC_VER) && _MSC_VER >= 1900)
16-
# include <time.h>
17-
#else
18-
# include <sys/time.h>
19-
#endif
22+
static int64_t gettime_us(void) {
23+
#if defined(_WIN32)
24+
FILETIME creation, exit, kernel, user;
2025

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);
26+
if (GetProcessTimes(GetCurrentProcess(), &creation, &exit, &kernel, &user) == 0) {
27+
return 0;
2828
}
29-
return (int64_t)tv.tv_nsec / 1000 + (int64_t)tv.tv_sec * 1000000LL;
30-
#else
29+
30+
ULARGE_INTEGER k, u;
31+
k.LowPart = kernel.dwLowDateTime;
32+
k.HighPart = kernel.dwHighDateTime;
33+
u.LowPart = user.dwLowDateTime;
34+
u.HighPart = user.dwHighDateTime;
35+
36+
return (int64_t)((k.QuadPart + u.QuadPart) / 10);
37+
#else /* POSIX */
38+
39+
# if defined(CLOCK_PROCESS_CPUTIME_ID)
40+
/* in theory, CLOCK_PROCESS_CPUTIME_ID is only useful if the process is locked to a core. see https://linux.die.net/man/3/clock_gettime */
41+
struct timespec ts;
42+
if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) != 0) {
43+
return 0;
44+
}
45+
return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
46+
# elif defined(CLOCK_MONOTONIC)
47+
/* WARN: timer is influenced by environvment (OS, scheduling, interrupts...) */
48+
struct timespec ts;
49+
if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
50+
return 0;
51+
}
52+
return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
53+
# elif defined(CLOCK_REALTIME)
54+
/* WARN: timer is influenced by environvment (OS, scheduling, interrupts...) */
55+
struct timespec ts;
56+
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
57+
return 0;
58+
}
59+
return (int64_t)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
60+
# else
61+
/* WARN: timer is influenced by environvment (OS, scheduling, interrupts...) */
3162
struct timeval tv;
32-
gettimeofday(&tv, NULL);
33-
return (int64_t)tv.tv_usec + (int64_t)tv.tv_sec * 1000000LL;
63+
gettimeofday((struct timeval*)&tv, NULL);
64+
return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
65+
# endif
66+
3467
#endif
3568
}
3669

@@ -44,9 +77,9 @@ static void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setu
4477
if (setup != NULL) {
4578
setup(data);
4679
}
47-
begin = gettime_i64();
80+
begin = gettime_us();
4881
benchmark(data, iter);
49-
total = gettime_i64() - begin;
82+
total = gettime_us() - begin;
5083
if (teardown != NULL) {
5184
teardown(data, iter);
5285
}

0 commit comments

Comments
 (0)