diff --git a/.gitignore b/.gitignore index 9e187a34a9606..aa7009af14855 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ valgrind_ctime_test *.exe *.so *.a +*.csv !.gitignore Makefile diff --git a/README.md b/README.md index 182c29d9ce5ef..7499f84d42065 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,18 @@ To create a HTML report with coloured and annotated source code: $ mkdir -p coverage $ gcovr --exclude 'src/bench*' --html --html-details -o coverage/coverage.html +Benchmark +------------ +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. + +To print the benchmark result to the command line: + + $ ./bench_name + +To create a CSV file for the benchmark result : + + $ ./bench_name | sed '2d;s/ \{1,\}//g' > bench_name.csv + Reporting a vulnerability ------------ diff --git a/src/bench.h b/src/bench.h index 63c55df44d059..0e4b770673562 100644 --- a/src/bench.h +++ b/src/bench.h @@ -24,7 +24,7 @@ static int64_t gettime_i64(void) { /* Format fixed point number. */ void print_number(const int64_t x) { int64_t x_abs, y; - int c, i, rounding; + int c, i, rounding, g; /* g = integer part size, c = fractional part size */ size_t ptr; char buffer[30]; @@ -56,21 +56,27 @@ void print_number(const int64_t x) { /* Format and print the number. */ ptr = sizeof(buffer) - 1; buffer[ptr] = 0; - if (c != 0) { + g = 0; + if (c != 0) { /* non zero fractional part */ for (i = 0; i < c; ++i) { buffer[--ptr] = '0' + (y % 10); y /= 10; } - buffer[--ptr] = '.'; + } else if (c == 0) { /* fractional part is 0 */ + buffer[--ptr] = '0'; } + buffer[--ptr] = '.'; do { buffer[--ptr] = '0' + (y % 10); y /= 10; + g++; } while (y != 0); if (x < 0) { buffer[--ptr] = '-'; + g++; } - printf("%s", &buffer[ptr]); + printf("%5.*s", g, &buffer[ptr]); /* Prints integer part */ + printf("%-*s", FP_EXP, &buffer[ptr + g]); /* Prints fractional part */ } void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void*), void (*teardown)(void*, int), void* data, int count, int iter) { @@ -97,13 +103,14 @@ void run_benchmark(char *name, void (*benchmark)(void*, int), void (*setup)(void } sum += total; } - printf("%s: min ", name); + /* ',' is used as a column delimiter */ + printf("%-30s, ", name); print_number(min * FP_MULT / iter); - printf("us / avg "); + printf(" , "); print_number(((sum * FP_MULT) / count) / iter); - printf("us / max "); + printf(" , "); print_number(max * FP_MULT / iter); - printf("us\n"); + printf("\n"); } int have_flag(int argc, char** argv, char *flag) { @@ -130,4 +137,13 @@ int get_iters(int default_iters) { } } +void print_output_table_header_row(void) { + char* bench_str = "Benchmark"; /* left justified */ + char* min_str = " Min(us) "; /* center alignment */ + char* avg_str = " Avg(us) "; + char* max_str = " Max(us) "; + printf("%-30s,%-15s,%-15s,%-15s\n", bench_str, min_str, avg_str, max_str); + printf("\n"); +} + #endif /* SECP256K1_BENCH_H */ diff --git a/src/bench_ecdh.c b/src/bench_ecdh.c index cb020d26b4d99..b6d4ee2941910 100644 --- a/src/bench_ecdh.c +++ b/src/bench_ecdh.c @@ -52,6 +52,8 @@ int main(void) { /* create a context with no capabilities */ data.ctx = secp256k1_context_create(SECP256K1_FLAGS_TYPE_CONTEXT); + print_output_table_header_row(); + run_benchmark("ecdh", bench_ecdh, bench_ecdh_setup, NULL, &data, 10, iters); secp256k1_context_destroy(data.ctx); diff --git a/src/bench_ecmult.c b/src/bench_ecmult.c index 420c4293c0333..37e8a5d510fda 100644 --- a/src/bench_ecmult.c +++ b/src/bench_ecmult.c @@ -333,6 +333,7 @@ int main(int argc, char **argv) { secp256k1_ge_set_all_gej_var(data.pubkeys, data.pubkeys_gej, POINTS); + print_output_table_header_row(); /* Initialize offset1 and offset2 */ hash_into_offset(&data, 0); run_ecmult_bench(&data, iters); diff --git a/src/bench_internal.c b/src/bench_internal.c index 161b1c4a47666..001dff1c1e404 100644 --- a/src/bench_internal.c +++ b/src/bench_internal.c @@ -344,6 +344,7 @@ void bench_context_sign(void* arg, int iters) { int main(int argc, char **argv) { bench_inv data; int iters = get_iters(20000); + print_output_table_header_row(); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "add")) run_benchmark("scalar_add", bench_scalar_add, bench_setup, NULL, &data, 10, iters*100); if (have_flag(argc, argv, "scalar") || have_flag(argc, argv, "negate")) run_benchmark("scalar_negate", bench_scalar_negate, bench_setup, NULL, &data, 10, iters*100); diff --git a/src/bench_recover.c b/src/bench_recover.c index 4bcac19dc0a39..3ccd86dd9bacd 100644 --- a/src/bench_recover.c +++ b/src/bench_recover.c @@ -55,6 +55,8 @@ int main(void) { data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY); + print_output_table_header_row(); + run_benchmark("ecdsa_recover", bench_recover, bench_recover_setup, NULL, &data, 10, iters); secp256k1_context_destroy(data.ctx); diff --git a/src/bench_schnorrsig.c b/src/bench_schnorrsig.c index d95bc00f485fb..e30735d8b9ee2 100644 --- a/src/bench_schnorrsig.c +++ b/src/bench_schnorrsig.c @@ -86,6 +86,7 @@ int main(void) { CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1); } + print_output_table_header_row(); run_benchmark("schnorrsig_sign", bench_schnorrsig_sign, NULL, NULL, (void *) &data, 10, iters); run_benchmark("schnorrsig_verify", bench_schnorrsig_verify, NULL, NULL, (void *) &data, 10, iters); diff --git a/src/bench_sign.c b/src/bench_sign.c index f659c18c92d0b..c44f7b10ba846 100644 --- a/src/bench_sign.c +++ b/src/bench_sign.c @@ -51,6 +51,8 @@ int main(void) { data.ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); + print_output_table_header_row(); + run_benchmark("ecdsa_sign", bench_sign_run, bench_sign_setup, NULL, &data, 10, iters); secp256k1_context_destroy(data.ctx); diff --git a/src/bench_verify.c b/src/bench_verify.c index 693a6fb95062e..d62e34b77ec16 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -63,6 +63,7 @@ int main(void) { data.pubkeylen = 33; CHECK(secp256k1_ec_pubkey_serialize(data.ctx, data.pubkey, &data.pubkeylen, &pubkey, SECP256K1_EC_COMPRESSED) == 1); + print_output_table_header_row(); run_benchmark("ecdsa_verify", bench_verify, NULL, NULL, &data, 10, iters); secp256k1_context_destroy(data.ctx);