From 26a255beb673217c839dcc51790d9a484f9a292d Mon Sep 17 00:00:00 2001 From: siv2r Date: Fri, 15 Oct 2021 07:21:35 +0530 Subject: [PATCH 1/2] Shared benchmark format for command line and CSV outputs 1. add `print_output_table_header_row` func to print the table header for benchmark output 2. modify the following benchmarks to include the table header - bench_ecdh.c - bench_ecmult.c - bench_internal.c - bench_recover.c - bench_schnorrsig.c - bench_sign.c - bench_verify.c --- src/bench.h | 32 ++++++++++++++++++++++++-------- src/bench_ecdh.c | 2 ++ src/bench_ecmult.c | 1 + src/bench_internal.c | 1 + src/bench_recover.c | 2 ++ src/bench_schnorrsig.c | 1 + src/bench_sign.c | 2 ++ src/bench_verify.c | 1 + 8 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/bench.h b/src/bench.h index 63c55df44d..0e4b770673 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 cb020d26b4..b6d4ee2941 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 420c4293c0..37e8a5d510 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 161b1c4a47..001dff1c1e 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 4bcac19dc0..3ccd86dd9b 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 d95bc00f48..e30735d8b9 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 f659c18c92..c44f7b10ba 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 565ae4beec..f0f123160a 100644 --- a/src/bench_verify.c +++ b/src/bench_verify.c @@ -103,6 +103,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); #ifdef ENABLE_OPENSSL_TESTS data.ec_group = EC_GROUP_new_by_curve_name(NID_secp256k1); From b4b130678db31a7cabc2cde091bc4acbca92b7a3 Mon Sep 17 00:00:00 2001 From: siv2r Date: Tue, 19 Oct 2021 06:11:59 +0530 Subject: [PATCH 2/2] create csv file from the benchmark output --- .gitignore | 1 + README.md | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/.gitignore b/.gitignore index 9e187a34a9..aa7009af14 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 182c29d9ce..7499f84d42 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 ------------