1 /* $OpenBSD: bn_general.c,v 1.2 2023/04/11 05:53:53 jsing Exp $ */ 2 /* 3 * Copyright (c) 2022, 2023 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/resource.h> 19 #include <sys/time.h> 20 21 #include <err.h> 22 #include <signal.h> 23 #include <stdio.h> 24 #include <string.h> 25 #include <time.h> 26 #include <unistd.h> 27 28 #include <openssl/bn.h> 29 30 static void 31 benchmark_bn_copy_setup(BIGNUM *dst, BIGNUM *src, int n) 32 { 33 if (!BN_set_bit(dst, n - 1)) 34 errx(1, "BN_set_bit"); 35 if (!BN_set_bit(src, n - 1)) 36 errx(1, "BN_set_bit"); 37 } 38 39 static void 40 benchmark_bn_copy_run_once(BIGNUM *dst, BIGNUM *src) 41 { 42 if (BN_copy(dst, src) == NULL) 43 errx(1, "BN_copy"); 44 } 45 46 struct benchmark { 47 const char *desc; 48 void (*setup)(BIGNUM *, BIGNUM *, int); 49 void (*run_once)(BIGNUM *, BIGNUM *); 50 int bits; 51 }; 52 53 struct benchmark benchmarks[] = { 54 { 55 .desc = "BN_copy() 32 bits", 56 .setup = benchmark_bn_copy_setup, 57 .run_once = benchmark_bn_copy_run_once, 58 .bits = 32, 59 }, 60 { 61 .desc = "BN_copy() 256 bits", 62 .setup = benchmark_bn_copy_setup, 63 .run_once = benchmark_bn_copy_run_once, 64 .bits = 256, 65 }, 66 { 67 .desc = "BN_copy() 320 bits", 68 .setup = benchmark_bn_copy_setup, 69 .run_once = benchmark_bn_copy_run_once, 70 .bits = 320, 71 }, 72 { 73 .desc = "BN_copy() 512 bits", 74 .setup = benchmark_bn_copy_setup, 75 .run_once = benchmark_bn_copy_run_once, 76 .bits = 512, 77 }, 78 { 79 .desc = "BN_copy() 1024 bits", 80 .setup = benchmark_bn_copy_setup, 81 .run_once = benchmark_bn_copy_run_once, 82 .bits = 1024, 83 }, 84 { 85 .desc = "BN_copy() 2048 bits", 86 .setup = benchmark_bn_copy_setup, 87 .run_once = benchmark_bn_copy_run_once, 88 .bits = 2048, 89 }, 90 { 91 .desc = "BN_copy() 4096 bits", 92 .setup = benchmark_bn_copy_setup, 93 .run_once = benchmark_bn_copy_run_once, 94 .bits = 4096, 95 }, 96 { 97 .desc = "BN_copy() 16384 bits", 98 .setup = benchmark_bn_copy_setup, 99 .run_once = benchmark_bn_copy_run_once, 100 .bits = 16384, 101 }, 102 }; 103 104 #define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0])) 105 106 static int benchmark_stop; 107 108 static void 109 benchmark_sig_alarm(int sig) 110 { 111 benchmark_stop = 1; 112 } 113 114 static void 115 benchmark_run(const struct benchmark *bm, int seconds) 116 { 117 struct timespec start, end, duration; 118 struct rusage rusage; 119 BIGNUM *dst, *src; 120 int i; 121 122 signal(SIGALRM, benchmark_sig_alarm); 123 124 if ((src = BN_new()) == NULL) 125 errx(1, "BN_new"); 126 if ((dst = BN_new()) == NULL) 127 errx(1, "BN_new"); 128 129 bm->setup(dst, src, bm->bits); 130 131 benchmark_stop = 0; 132 i = 0; 133 alarm(seconds); 134 135 if (getrusage(RUSAGE_SELF, &rusage) == -1) 136 err(1, "getrusage failed"); 137 TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &start); 138 139 fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds); 140 while (!benchmark_stop) { 141 bm->run_once(dst, src); 142 i++; 143 } 144 if (getrusage(RUSAGE_SELF, &rusage) == -1) 145 err(1, "getrusage failed"); 146 TIMEVAL_TO_TIMESPEC(&rusage.ru_utime, &end); 147 148 timespecsub(&end, &start, &duration); 149 fprintf(stderr, "%d iterations in %f seconds - %llu op/s\n", i, 150 duration.tv_sec + duration.tv_nsec / 1000000000.0, 151 (uint64_t)i * 1000000000 / 152 (duration.tv_sec * 1000000000 + duration.tv_nsec)); 153 154 BN_free(src); 155 BN_free(dst); 156 } 157 158 static void 159 benchmark_bn_general(void) 160 { 161 const struct benchmark *bm; 162 size_t i; 163 164 for (i = 0; i < N_BENCHMARKS; i++) { 165 bm = &benchmarks[i]; 166 benchmark_run(bm, 5); 167 } 168 } 169 170 int 171 main(int argc, char **argv) 172 { 173 int benchmark = 0, failed = 0; 174 175 if (argc == 2 && strcmp(argv[1], "--benchmark") == 0) 176 benchmark = 1; 177 178 if (benchmark && !failed) 179 benchmark_bn_general(); 180 181 return failed; 182 } 183