Provide benchmarks for BN_copy()
authorjsing <jsing@openbsd.org>
Mon, 10 Apr 2023 19:02:30 +0000 (19:02 +0000)
committerjsing <jsing@openbsd.org>
Mon, 10 Apr 2023 19:02:30 +0000 (19:02 +0000)
regress/lib/libcrypto/bn/Makefile
regress/lib/libcrypto/bn/bn_general.c [new file with mode: 0644]

index 71909ed..5df3037 100644 (file)
@@ -1,8 +1,9 @@
-#      $OpenBSD: Makefile,v 1.28 2023/04/10 13:57:57 tb Exp $
+#      $OpenBSD: Makefile,v 1.29 2023/04/10 19:02:30 jsing Exp $
 
 PROGS +=       bn_add_sub
 PROGS +=       bn_cmp
 PROGS +=       bn_gcd
+PROGS +=       bn_general
 PROGS +=       bn_isqrt
 PROGS +=       bn_mod_exp
 PROGS +=       bn_mod_sqrt
diff --git a/regress/lib/libcrypto/bn/bn_general.c b/regress/lib/libcrypto/bn/bn_general.c
new file mode 100644 (file)
index 0000000..94f7af1
--- /dev/null
@@ -0,0 +1,182 @@
+/*     $OpenBSD: bn_general.c,v 1.1 2023/04/10 19:02:30 jsing Exp $ */
+/*
+ * Copyright (c) 2022, 2023 Joel Sing <jsing@openbsd.org>
+ *
+ * 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 <sys/resource.h>
+#include <sys/time.h>
+
+#include <err.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+
+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,
+           (size_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;
+}