master
1// zig run -O ReleaseFast --zig-lib-dir ../.. benchmark.zig
2
3const std = @import("std");
4const builtin = @import("builtin");
5const mem = std.mem;
6const time = std.time;
7const Timer = time.Timer;
8const crypto = std.crypto;
9
10const KiB = 1024;
11const MiB = 1024 * KiB;
12
13var prng = std.Random.DefaultPrng.init(0);
14const random = prng.random();
15
16const Crypto = struct {
17 ty: type,
18 name: []const u8,
19};
20
21const hashes = [_]Crypto{
22 Crypto{ .ty = crypto.hash.ascon.AsconHash256, .name = "ascon-256" },
23 Crypto{ .ty = crypto.hash.Md5, .name = "md5" },
24 Crypto{ .ty = crypto.hash.Sha1, .name = "sha1" },
25 Crypto{ .ty = crypto.hash.sha2.Sha256, .name = "sha256" },
26 Crypto{ .ty = crypto.hash.sha2.Sha512, .name = "sha512" },
27 Crypto{ .ty = crypto.hash.sha3.Sha3_256, .name = "sha3-256" },
28 Crypto{ .ty = crypto.hash.sha3.Sha3_512, .name = "sha3-512" },
29 Crypto{ .ty = crypto.hash.sha3.Shake128, .name = "shake-128" },
30 Crypto{ .ty = crypto.hash.sha3.Shake256, .name = "shake-256" },
31 Crypto{ .ty = crypto.hash.sha3.TurboShake128(null), .name = "turboshake-128" },
32 Crypto{ .ty = crypto.hash.sha3.TurboShake256(null), .name = "turboshake-256" },
33 Crypto{ .ty = crypto.hash.sha3.KT128, .name = "kt128" },
34 Crypto{ .ty = crypto.hash.blake2.Blake2s256, .name = "blake2s" },
35 Crypto{ .ty = crypto.hash.blake2.Blake2b512, .name = "blake2b" },
36 Crypto{ .ty = crypto.hash.Blake3, .name = "blake3" },
37};
38
39const parallel_hashes = [_]Crypto{
40 Crypto{ .ty = crypto.hash.Blake3, .name = "blake3-parallel" },
41 Crypto{ .ty = crypto.hash.sha3.KT128, .name = "kt128-parallel" },
42};
43
44const block_size: usize = 8 * 8192;
45
46pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 {
47 const blocks_count = bytes / block_size;
48 var block: [block_size]u8 = undefined;
49 random.bytes(&block);
50
51 var h = Hash.init(.{});
52
53 var timer = try Timer.start();
54 const start = timer.lap();
55 for (0..blocks_count) |_| {
56 h.update(&block);
57 }
58 var final: [Hash.digest_length]u8 = undefined;
59 h.final(&final);
60 std.mem.doNotOptimizeAway(final);
61
62 const end = timer.read();
63
64 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
65 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
66
67 return throughput;
68}
69
70pub fn benchmarkHashParallel(comptime Hash: anytype, comptime bytes: comptime_int, allocator: mem.Allocator, io: std.Io) !u64 {
71 const data: []u8 = try allocator.alloc(u8, bytes);
72 defer allocator.free(data);
73 random.bytes(data);
74
75 var timer = try Timer.start();
76 const start = timer.lap();
77 var final: [Hash.digest_length]u8 = undefined;
78 try Hash.hashParallel(data, &final, .{}, allocator, io);
79 std.mem.doNotOptimizeAway(final);
80
81 const end = timer.read();
82
83 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
84 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
85
86 return throughput;
87}
88
89const macs = [_]Crypto{
90 Crypto{ .ty = crypto.onetimeauth.Ghash, .name = "ghash" },
91 Crypto{ .ty = crypto.onetimeauth.Polyval, .name = "polyval" },
92 Crypto{ .ty = crypto.onetimeauth.Poly1305, .name = "poly1305" },
93 Crypto{ .ty = crypto.auth.hmac.HmacMd5, .name = "hmac-md5" },
94 Crypto{ .ty = crypto.auth.hmac.HmacSha1, .name = "hmac-sha1" },
95 Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha256, .name = "hmac-sha256" },
96 Crypto{ .ty = crypto.auth.hmac.sha2.HmacSha512, .name = "hmac-sha512" },
97 Crypto{ .ty = crypto.auth.siphash.SipHash64(2, 4), .name = "siphash-2-4" },
98 Crypto{ .ty = crypto.auth.siphash.SipHash64(1, 3), .name = "siphash-1-3" },
99 Crypto{ .ty = crypto.auth.siphash.SipHash128(2, 4), .name = "siphash128-2-4" },
100 Crypto{ .ty = crypto.auth.siphash.SipHash128(1, 3), .name = "siphash128-1-3" },
101 Crypto{ .ty = crypto.auth.aegis.Aegis128X4Mac, .name = "aegis-128x4 mac" },
102 Crypto{ .ty = crypto.auth.aegis.Aegis256X4Mac, .name = "aegis-256x4 mac" },
103 Crypto{ .ty = crypto.auth.aegis.Aegis128X2Mac, .name = "aegis-128x2 mac" },
104 Crypto{ .ty = crypto.auth.aegis.Aegis256X2Mac, .name = "aegis-256x2 mac" },
105 Crypto{ .ty = crypto.auth.aegis.Aegis128LMac, .name = "aegis-128l mac" },
106 Crypto{ .ty = crypto.auth.aegis.Aegis256Mac, .name = "aegis-256 mac" },
107 Crypto{ .ty = crypto.auth.cmac.CmacAes128, .name = "aes-cmac" },
108};
109
110pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
111 var in: [512 * KiB]u8 = undefined;
112 random.bytes(in[0..]);
113
114 const key_length = if (Mac.key_length == 0) 32 else Mac.key_length;
115 var key: [key_length]u8 = undefined;
116 random.bytes(key[0..]);
117
118 var mac: [Mac.mac_length]u8 = undefined;
119 var offset: usize = 0;
120 var timer = try Timer.start();
121 const start = timer.lap();
122 while (offset < bytes) : (offset += in.len) {
123 Mac.create(mac[0..], in[0..], key[0..]);
124 mem.doNotOptimizeAway(&mac);
125 }
126 const end = timer.read();
127
128 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
129 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
130
131 return throughput;
132}
133
134const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }};
135
136pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 {
137 std.debug.assert(DhKeyExchange.shared_length >= DhKeyExchange.secret_length);
138
139 var secret: [DhKeyExchange.shared_length]u8 = undefined;
140 random.bytes(secret[0..]);
141
142 var public: [DhKeyExchange.shared_length]u8 = undefined;
143 random.bytes(public[0..]);
144
145 var timer = try Timer.start();
146 const start = timer.lap();
147 {
148 var i: usize = 0;
149 while (i < exchange_count) : (i += 1) {
150 const out = try DhKeyExchange.scalarmult(secret, public);
151 secret[0..16].* = out[0..16].*;
152 public[0..16].* = out[16..32].*;
153 mem.doNotOptimizeAway(&out);
154 }
155 }
156 const end = timer.read();
157
158 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
159 const throughput = @as(u64, @intFromFloat(exchange_count / elapsed_s));
160
161 return throughput;
162}
163
164const signatures = [_]Crypto{
165 Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" },
166 Crypto{ .ty = crypto.sign.ecdsa.EcdsaP256Sha256, .name = "ecdsa-p256" },
167 Crypto{ .ty = crypto.sign.ecdsa.EcdsaP384Sha384, .name = "ecdsa-p384" },
168 Crypto{ .ty = crypto.sign.ecdsa.EcdsaSecp256k1Sha256, .name = "ecdsa-secp256k1" },
169 Crypto{ .ty = crypto.sign.mldsa.MLDSA44, .name = "ml-dsa-44" },
170 Crypto{ .ty = crypto.sign.mldsa.MLDSA65, .name = "ml-dsa-65" },
171 Crypto{ .ty = crypto.sign.mldsa.MLDSA87, .name = "ml-dsa-87" },
172};
173
174pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
175 const msg = [_]u8{0} ** 64;
176 const key_pair = Signature.KeyPair.generate();
177
178 var timer = try Timer.start();
179 const start = timer.lap();
180 {
181 var i: usize = 0;
182 while (i < signatures_count) : (i += 1) {
183 const sig = try key_pair.sign(&msg, null);
184 mem.doNotOptimizeAway(&sig);
185 }
186 }
187 const end = timer.read();
188
189 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
190 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
191
192 return throughput;
193}
194
195const signature_verifications = [_]Crypto{
196 Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" },
197 Crypto{ .ty = crypto.sign.mldsa.MLDSA44, .name = "ml-dsa-44" },
198 Crypto{ .ty = crypto.sign.mldsa.MLDSA65, .name = "ml-dsa-65" },
199 Crypto{ .ty = crypto.sign.mldsa.MLDSA87, .name = "ml-dsa-87" },
200};
201
202pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
203 const msg = [_]u8{0} ** 64;
204 const key_pair = Signature.KeyPair.generate();
205 const sig = try key_pair.sign(&msg, null);
206
207 var timer = try Timer.start();
208 const start = timer.lap();
209 {
210 var i: usize = 0;
211 while (i < signatures_count) : (i += 1) {
212 try sig.verify(&msg, key_pair.public_key);
213 mem.doNotOptimizeAway(&sig);
214 }
215 }
216 const end = timer.read();
217
218 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
219 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
220
221 return throughput;
222}
223
224const batch_signature_verifications = [_]Crypto{Crypto{ .ty = crypto.sign.Ed25519, .name = "ed25519" }};
225
226pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime signatures_count: comptime_int) !u64 {
227 const msg = [_]u8{0} ** 64;
228 const key_pair = Signature.KeyPair.generate();
229 const sig = try key_pair.sign(&msg, null);
230
231 var batch: [64]Signature.BatchElement = undefined;
232 for (&batch) |*element| {
233 element.* = Signature.BatchElement{ .sig = sig, .msg = &msg, .public_key = key_pair.public_key };
234 }
235
236 var timer = try Timer.start();
237 const start = timer.lap();
238 {
239 var i: usize = 0;
240 while (i < signatures_count) : (i += 1) {
241 try Signature.verifyBatch(batch.len, batch);
242 mem.doNotOptimizeAway(&sig);
243 }
244 }
245 const end = timer.read();
246
247 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
248 const throughput = batch.len * @as(u64, @intFromFloat(signatures_count / elapsed_s));
249
250 return throughput;
251}
252
253const kems = [_]Crypto{
254 Crypto{ .ty = crypto.kem.kyber_d00.Kyber512, .name = "kyber512d00" },
255 Crypto{ .ty = crypto.kem.kyber_d00.Kyber768, .name = "kyber768d00" },
256 Crypto{ .ty = crypto.kem.kyber_d00.Kyber1024, .name = "kyber1024d00" },
257};
258
259pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int) !u64 {
260 const key_pair = Kem.KeyPair.generate();
261
262 var timer = try Timer.start();
263 const start = timer.lap();
264 {
265 var i: usize = 0;
266 while (i < kems_count) : (i += 1) {
267 const e = key_pair.public_key.encaps(null);
268 mem.doNotOptimizeAway(&e);
269 }
270 }
271 const end = timer.read();
272
273 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
274 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
275
276 return throughput;
277}
278
279pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_int) !u64 {
280 const key_pair = Kem.KeyPair.generate();
281
282 const e = key_pair.public_key.encaps(null);
283
284 var timer = try Timer.start();
285 const start = timer.lap();
286 {
287 var i: usize = 0;
288 while (i < kems_count) : (i += 1) {
289 const ss2 = try key_pair.secret_key.decaps(&e.ciphertext);
290 mem.doNotOptimizeAway(&ss2);
291 }
292 }
293 const end = timer.read();
294
295 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
296 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
297
298 return throughput;
299}
300
301pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_int) !u64 {
302 var timer = try Timer.start();
303 const start = timer.lap();
304 {
305 var i: usize = 0;
306 while (i < kems_count) : (i += 1) {
307 const key_pair = Kem.KeyPair.generate();
308 mem.doNotOptimizeAway(&key_pair);
309 }
310 }
311 const end = timer.read();
312
313 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
314 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
315
316 return throughput;
317}
318
319const aeads = [_]Crypto{
320 Crypto{ .ty = crypto.aead.ascon.AsconAead128, .name = "ascon-aead-128" },
321 Crypto{ .ty = crypto.aead.chacha_poly.ChaCha20Poly1305, .name = "chacha20Poly1305" },
322 Crypto{ .ty = crypto.aead.chacha_poly.XChaCha20Poly1305, .name = "xchacha20Poly1305" },
323 Crypto{ .ty = crypto.aead.chacha_poly.XChaCha8Poly1305, .name = "xchacha8Poly1305" },
324 Crypto{ .ty = crypto.aead.salsa_poly.XSalsa20Poly1305, .name = "xsalsa20Poly1305" },
325 Crypto{ .ty = crypto.aead.aegis.Aegis128X4, .name = "aegis-128x4" },
326 Crypto{ .ty = crypto.aead.aegis.Aegis128X2, .name = "aegis-128x2" },
327 Crypto{ .ty = crypto.aead.aegis.Aegis128L, .name = "aegis-128l" },
328 Crypto{ .ty = crypto.aead.aegis.Aegis256X4, .name = "aegis-256x4" },
329 Crypto{ .ty = crypto.aead.aegis.Aegis256X2, .name = "aegis-256x2" },
330 Crypto{ .ty = crypto.aead.aegis.Aegis256, .name = "aegis-256" },
331 Crypto{ .ty = crypto.aead.aes_gcm.Aes128Gcm, .name = "aes128-gcm" },
332 Crypto{ .ty = crypto.aead.aes_gcm.Aes256Gcm, .name = "aes256-gcm" },
333 Crypto{ .ty = crypto.aead.aes_ocb.Aes128Ocb, .name = "aes128-ocb" },
334 Crypto{ .ty = crypto.aead.aes_ocb.Aes256Ocb, .name = "aes256-ocb" },
335 Crypto{ .ty = crypto.aead.isap.IsapA128A, .name = "isapa128a" },
336};
337
338pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 {
339 var in: [512 * KiB]u8 = undefined;
340 random.bytes(in[0..]);
341
342 var tag: [Aead.tag_length]u8 = undefined;
343
344 var key: [Aead.key_length]u8 = undefined;
345 random.bytes(key[0..]);
346
347 var nonce: [Aead.nonce_length]u8 = undefined;
348 random.bytes(nonce[0..]);
349
350 var offset: usize = 0;
351 var timer = try Timer.start();
352 const start = timer.lap();
353 while (offset < bytes) : (offset += in.len) {
354 Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key);
355 try Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key);
356 }
357 mem.doNotOptimizeAway(&in);
358 const end = timer.read();
359
360 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
361 const throughput = @as(u64, @intFromFloat(2 * bytes / elapsed_s));
362
363 return throughput;
364}
365
366const aes = [_]Crypto{
367 Crypto{ .ty = crypto.core.aes.Aes128, .name = "aes128-single" },
368 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-single" },
369};
370
371pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int) !u64 {
372 var key: [Aes.key_bits / 8]u8 = undefined;
373 random.bytes(key[0..]);
374 const ctx = Aes.initEnc(key);
375
376 var in = [_]u8{0} ** 16;
377
378 var timer = try Timer.start();
379 const start = timer.lap();
380 {
381 var i: usize = 0;
382 while (i < count) : (i += 1) {
383 ctx.encrypt(&in, &in);
384 }
385 }
386 mem.doNotOptimizeAway(&in);
387 const end = timer.read();
388
389 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
390 const throughput = @as(u64, @intFromFloat(count / elapsed_s));
391
392 return throughput;
393}
394
395const aes8 = [_]Crypto{
396 Crypto{ .ty = crypto.core.aes.Aes128, .name = "aes128-8" },
397 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-8" },
398};
399
400pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int) !u64 {
401 var key: [Aes.key_bits / 8]u8 = undefined;
402 random.bytes(key[0..]);
403 const ctx = Aes.initEnc(key);
404
405 var in = [_]u8{0} ** (8 * 16);
406
407 var timer = try Timer.start();
408 const start = timer.lap();
409 {
410 var i: usize = 0;
411 while (i < count) : (i += 1) {
412 ctx.encryptWide(8, &in, &in);
413 }
414 }
415 mem.doNotOptimizeAway(&in);
416 const end = timer.read();
417
418 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
419 const throughput = @as(u64, @intFromFloat(8 * count / elapsed_s));
420
421 return throughput;
422}
423
424const CryptoPwhash = struct {
425 ty: type,
426 params: *const anyopaque,
427 name: []const u8,
428};
429const bcrypt_params = crypto.pwhash.bcrypt.Params{ .rounds_log = 8, .silently_truncate_password = true };
430const pwhashes = [_]CryptoPwhash{
431 .{
432 .ty = crypto.pwhash.bcrypt,
433 .params = &bcrypt_params,
434 .name = "bcrypt",
435 },
436 .{
437 .ty = crypto.pwhash.scrypt,
438 .params = &crypto.pwhash.scrypt.Params.interactive,
439 .name = "scrypt",
440 },
441 .{
442 .ty = crypto.pwhash.argon2,
443 .params = &crypto.pwhash.argon2.Params.interactive_2id,
444 .name = "argon2",
445 },
446};
447
448fn benchmarkPwhash(
449 allocator: mem.Allocator,
450 comptime ty: anytype,
451 comptime params: *const anyopaque,
452 comptime count: comptime_int,
453) !f64 {
454 const password = "testpass" ** 2;
455 const opts = ty.HashOptions{
456 .allocator = allocator,
457 .params = @as(*const ty.Params, @ptrCast(@alignCast(params))).*,
458 .encoding = .phc,
459 };
460 var buf: [256]u8 = undefined;
461
462 var timer = try Timer.start();
463 const start = timer.lap();
464 {
465 var i: usize = 0;
466 while (i < count) : (i += 1) {
467 _ = try ty.strHash(password, opts, &buf);
468 mem.doNotOptimizeAway(&buf);
469 }
470 }
471 const end = timer.read();
472
473 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
474 const throughput = elapsed_s / count;
475
476 return throughput;
477}
478
479fn usage() void {
480 std.debug.print(
481 \\throughput_test [options]
482 \\
483 \\Options:
484 \\ --filter [test-name]
485 \\ --seed [int]
486 \\ --help
487 \\
488 , .{});
489}
490
491fn mode(comptime x: comptime_int) comptime_int {
492 return if (builtin.mode == .Debug) x / 64 else x;
493}
494
495pub fn main() !void {
496 // Size of buffer is about size of printed message.
497 var stdout_buffer: [0x100]u8 = undefined;
498 var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
499 const stdout = &stdout_writer.interface;
500
501 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
502 defer arena.deinit();
503 const arena_allocator = arena.allocator();
504 const args = try std.process.argsAlloc(arena_allocator);
505
506 var filter: ?[]u8 = "";
507
508 var i: usize = 1;
509 while (i < args.len) : (i += 1) {
510 if (std.mem.eql(u8, args[i], "--mode")) {
511 try stdout.print("{}\n", .{builtin.mode});
512 try stdout.flush();
513 return;
514 } else if (std.mem.eql(u8, args[i], "--seed")) {
515 i += 1;
516 if (i == args.len) {
517 usage();
518 std.process.exit(1);
519 }
520
521 const seed = try std.fmt.parseUnsigned(u32, args[i], 10);
522 prng.seed(seed);
523 } else if (std.mem.eql(u8, args[i], "--filter")) {
524 i += 1;
525 if (i == args.len) {
526 usage();
527 std.process.exit(1);
528 }
529
530 filter = args[i];
531 } else if (std.mem.eql(u8, args[i], "--help")) {
532 usage();
533 return;
534 } else {
535 usage();
536 std.process.exit(1);
537 }
538 }
539
540 inline for (hashes) |H| {
541 if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) {
542 const throughput = try benchmarkHash(H.ty, mode(128 * MiB));
543 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });
544 try stdout.flush();
545 }
546 }
547
548 var io_threaded = std.Io.Threaded.init(arena_allocator);
549 defer io_threaded.deinit();
550 const io = io_threaded.io();
551
552 inline for (parallel_hashes) |H| {
553 if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) {
554 const throughput = try benchmarkHashParallel(H.ty, mode(128 * MiB), arena_allocator, io);
555 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });
556 try stdout.flush();
557 }
558 }
559
560 inline for (macs) |M| {
561 if (filter == null or std.mem.indexOf(u8, M.name, filter.?) != null) {
562 const throughput = try benchmarkMac(M.ty, mode(128 * MiB));
563 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ M.name, throughput / (1 * MiB) });
564 try stdout.flush();
565 }
566 }
567
568 inline for (exchanges) |E| {
569 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
570 const throughput = try benchmarkKeyExchange(E.ty, mode(1000));
571 try stdout.print("{s:>17}: {:10} exchanges/s\n", .{ E.name, throughput });
572 try stdout.flush();
573 }
574 }
575
576 inline for (signatures) |E| {
577 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
578 const throughput = try benchmarkSignature(E.ty, mode(1000));
579 try stdout.print("{s:>17}: {:10} signatures/s\n", .{ E.name, throughput });
580 try stdout.flush();
581 }
582 }
583
584 inline for (signature_verifications) |E| {
585 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
586 const throughput = try benchmarkSignatureVerification(E.ty, mode(1000));
587 try stdout.print("{s:>17}: {:10} verifications/s\n", .{ E.name, throughput });
588 try stdout.flush();
589 }
590 }
591
592 inline for (batch_signature_verifications) |E| {
593 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
594 const throughput = try benchmarkBatchSignatureVerification(E.ty, mode(1000));
595 try stdout.print("{s:>17}: {:10} verifications/s (batch)\n", .{ E.name, throughput });
596 try stdout.flush();
597 }
598 }
599
600 inline for (aeads) |E| {
601 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
602 const throughput = try benchmarkAead(E.ty, mode(128 * MiB));
603 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ E.name, throughput / (1 * MiB) });
604 try stdout.flush();
605 }
606 }
607
608 inline for (aes) |E| {
609 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
610 const throughput = try benchmarkAes(E.ty, mode(100000000));
611 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
612 try stdout.flush();
613 }
614 }
615
616 inline for (aes8) |E| {
617 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
618 const throughput = try benchmarkAes8(E.ty, mode(10000000));
619 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
620 try stdout.flush();
621 }
622 }
623
624 inline for (pwhashes) |H| {
625 if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) {
626 const throughput = try benchmarkPwhash(arena_allocator, H.ty, H.params, mode(64));
627 try stdout.print("{s:>17}: {d:10.3} s/ops\n", .{ H.name, throughput });
628 try stdout.flush();
629 }
630 }
631
632 inline for (kems) |E| {
633 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
634 const throughput = try benchmarkKem(E.ty, mode(1000));
635 try stdout.print("{s:>17}: {:10} encaps/s\n", .{ E.name, throughput });
636 try stdout.flush();
637 }
638 }
639
640 inline for (kems) |E| {
641 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
642 const throughput = try benchmarkKemDecaps(E.ty, mode(25000));
643 try stdout.print("{s:>17}: {:10} decaps/s\n", .{ E.name, throughput });
644 try stdout.flush();
645 }
646 }
647
648 inline for (kems) |E| {
649 if (filter == null or std.mem.indexOf(u8, E.name, filter.?) != null) {
650 const throughput = try benchmarkKemKeyGen(E.ty, mode(25000));
651 try stdout.print("{s:>17}: {:10} keygen/s\n", .{ E.name, throughput });
652 try stdout.flush();
653 }
654 }
655}