/* $OpenBSD: bn_general.c,v 1.2 2023/04/11 05:53:53 jsing Exp $ */ /* * Copyright (c) 2022, 2023 Joel Sing * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include #include #include static void benchmark_bn_copy_setup(BIGNUM *dst, BIGNUM *src, int n) { if (!BN_set_bit(dst, n - 1)) errx(1, "BN_set_bit"); if (!BN_set_bit(src, n - 1)) errx(1, "BN_set_bit"); } static void benchmark_bn_copy_run_once(BIGNUM *dst, BIGNUM *src) { if (BN_copy(dst, src) == NULL) errx(1, "BN_copy"); } struct benchmark { const char *desc; void (*setup)(BIGNUM *, BIGNUM *, int); void (*run_once)(BIGNUM *, BIGNUM *); int bits; }; struct benchmark benchmarks[] = { { .desc = "BN_copy() 32 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 32, }, { .desc = "BN_copy() 256 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 256, }, { .desc = "BN_copy() 320 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 320, }, { .desc = "BN_copy() 512 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 512, }, { .desc = "BN_copy() 1024 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 1024, }, { .desc = "BN_copy() 2048 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 2048, }, { .desc = "BN_copy() 4096 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 4096, }, { .desc = "BN_copy() 16384 bits", .setup = benchmark_bn_copy_setup, .run_once = benchmark_bn_copy_run_once, .bits = 16384, }, }; #define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0])) static int benchmark_stop; static void benchmark_sig_alarm(int sig) { benchmark_stop = 1; } static void benchmark_run(const struct benchmark *bm, int seconds) { struct timespec start, end, duration; struct rusage rusage; BIGNUM *dst, *src; int i; signal(SIGALRM, benchmark_sig_alarm); if ((src = BN_new()) == NULL) errx(1, "BN_new"); if ((dst = BN_new()) == NULL) errx(1, "BN_new"); bm->setup(dst, src, bm->bits); benchmark_stop = 0; i = 0; alarm(seconds); if (getrusage(RUSAGE_SELF, &rusage) == -1) err(1, "getrusage failed"); TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &start); fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds); while (!benchmark_stop) { bm->run_once(dst, src); i++; } if (getrusage(RUSAGE_SELF, &rusage) == -1) err(1, "getrusage failed"); TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &end); timespecsub(&end, &start, &duration); fprintf(stderr, "%d iterations in %f seconds - %llu op/s\n", i, duration.tv_sec + duration.tv_nsec / 1000000000.0, (uint64_t)i * 1000000000 / (duration.tv_sec * 1000000000 + duration.tv_nsec)); BN_free(src); BN_free(dst); } static void benchmark_bn_general(void) { const struct benchmark *bm; size_t i; for (i = 0; i < N_BENCHMARKS; i++) { bm = &benchmarks[i]; benchmark_run(bm, 5); } } int main(int argc, char **argv) { int benchmark = 0, failed = 0; if (argc == 2 && strcmp(argv[1], "--benchmark") == 0) benchmark = 1; if (benchmark && !failed) benchmark_bn_general(); return failed; }