authorgravatar for uraniazpm@noreply.codeberg.orgUraniaZPM <uraniazpm@noreply.codeberg.org> 2026-03-18 21:00:08+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-18 21:00:08+01:00
log485b996b6159babb865dbdc009428677ef01e50c
treeba5edd90f91f61fe17661c910045588f8d05fdb4
parentce1f7136ae6db5809d077ccc52639befd73f50c0

Make benchmarking use std.Io.Clock.awake for timing (#31553)

In #31086, the `std.time.Timer` struct was removed, but this broke the last few programs that used it, those being the benchmarking programs for `std.Random`, `std.hash`, `std.crypto` and `std.unicode`. One more is `zig/perf_test.zig`, but as far as I can tell, that one is broken due to changes in file import rules too, unless I'm launching it wrong. I also spotted some performance and benchmarking issues with the RNGs, detailed in #31554. Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31553 Reviewed-by: Andrew Kelley <andrew@ziglang.org> Co-authored-by: UraniaZPM <uraniazpm@noreply.codeberg.org> Co-committed-by: UraniaZPM <uraniazpm@noreply.codeberg.org>

4 files changed, 95 insertions(+), 97 deletions(-)

lib/std/Random/benchmark.zig+11-9
......@@ -5,7 +5,6 @@ const builtin = @import("builtin");
55const std = @import("std");
66const Io = std.Io;
77const time = std.time;
8const Timer = time.Timer;
98const Random = std.Random;
109
1110const KiB = 1024;
......@@ -72,7 +71,11 @@ const Result = struct {
7271const long_block_size: usize = 8 * 8192;
7372const short_block_size: usize = 8;
7473
75pub fn benchmark(comptime H: anytype, bytes: usize, comptime block_size: usize) !Result {
74pub fn benchTime(io: Io) i96 {
75 return Io.Clock.awake.now(io).nanoseconds;
76}
77
78pub fn benchmark(comptime H: anytype, io: Io, bytes: usize, comptime block_size: usize) !Result {
7679 var rng = blk: {
7780 if (H.init_u8s) |init| {
7881 break :blk H.ty.init(init[0..].*);
......@@ -86,12 +89,11 @@ pub fn benchmark(comptime H: anytype, bytes: usize, comptime block_size: usize)
8689 var block: [block_size]u8 = undefined;
8790
8891 var offset: usize = 0;
89 var timer = try Timer.start();
90 const start = timer.lap();
92 const start = benchTime(io);
9193 while (offset < bytes) : (offset += block.len) {
9294 rng.fill(block[0..]);
9395 }
94 const end = timer.read();
96 const end = benchTime(io);
9597
9698 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
9799 const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));
......@@ -187,7 +189,7 @@ pub fn main(init: std.process.Init) !void {
187189 try stdout.print("{s} (long outputs)\n", .{R.name});
188190 try stdout.flush();
189191
190 const result_long = try benchmark(R, count, long_block_size);
192 const result_long = try benchmark(R, io, count, long_block_size);
191193 try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
192194 }
193195 }
......@@ -198,7 +200,7 @@ pub fn main(init: std.process.Init) !void {
198200 try stdout.print("{s} (short outputs)\n", .{R.name});
199201 try stdout.flush();
200202
201 const result_short = try benchmark(R, count, short_block_size);
203 const result_short = try benchmark(R, io, count, short_block_size);
202204 try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
203205 }
204206 }
......@@ -211,7 +213,7 @@ pub fn main(init: std.process.Init) !void {
211213 try stdout.print("{s} (cryptographic, long outputs)\n", .{R.name});
212214 try stdout.flush();
213215
214 const result_long = try benchmark(R, count, long_block_size);
216 const result_long = try benchmark(R, io, count, long_block_size);
215217 try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
216218 }
217219 }
......@@ -222,7 +224,7 @@ pub fn main(init: std.process.Init) !void {
222224 try stdout.print("{s} (cryptographic, short outputs)\n", .{R.name});
223225 try stdout.flush();
224226
225 const result_short = try benchmark(R, count, short_block_size);
227 const result_short = try benchmark(R, io, count, short_block_size);
226228 try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
227229 }
228230 }
lib/std/crypto/benchmark.zig+44-55
......@@ -6,7 +6,6 @@ const std = @import("std");
66const Io = std.Io;
77const mem = std.mem;
88const time = std.time;
9const Timer = std.time.Timer;
109const crypto = std.crypto;
1110
1211const KiB = 1024;
......@@ -45,15 +44,18 @@ const parallel_hashes = [_]Crypto{
4544
4645const block_size: usize = 8 * 8192;
4746
48pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 {
47pub fn benchTime(io: Io) i96 {
48 return Io.Clock.awake.now(io).nanoseconds;
49}
50
51pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int, io: Io) !u64 {
4952 const blocks_count = bytes / block_size;
5053 var block: [block_size]u8 = undefined;
5154 random.bytes(&block);
5255
5356 var h = Hash.init(.{});
5457
55 var timer = try Timer.start();
56 const start = timer.lap();
58 const start = benchTime(io);
5759 for (0..blocks_count) |_| {
5860 h.update(&block);
5961 }
......@@ -61,7 +63,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
6163 h.final(&final);
6264 std.mem.doNotOptimizeAway(final);
6365
64 const end = timer.read();
66 const end = benchTime(io);
6567
6668 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
6769 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
......@@ -74,13 +76,12 @@ pub fn benchmarkHashParallel(comptime Hash: anytype, comptime bytes: comptime_in
7476 defer allocator.free(data);
7577 random.bytes(data);
7678
77 var timer = try Timer.start();
78 const start = timer.lap();
79 const start = benchTime(io);
7980 var final: [Hash.digest_length]u8 = undefined;
8081 try Hash.hashParallel(data, &final, .{}, allocator, io);
8182 std.mem.doNotOptimizeAway(final);
8283
83 const end = timer.read();
84 const end = benchTime(io);
8485
8586 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
8687 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
......@@ -109,7 +110,7 @@ const macs = [_]Crypto{
109110 Crypto{ .ty = crypto.auth.cmac.CmacAes128, .name = "aes-cmac" },
110111};
111112
112pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
113pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int, io: Io) !u64 {
113114 var in: [512 * KiB]u8 = undefined;
114115 random.bytes(in[0..]);
115116
......@@ -119,13 +120,12 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
119120
120121 var mac: [Mac.mac_length]u8 = undefined;
121122 var offset: usize = 0;
122 var timer = try Timer.start();
123 const start = timer.lap();
123 const start = benchTime(io);
124124 while (offset < bytes) : (offset += in.len) {
125125 Mac.create(mac[0..], in[0..], key[0..]);
126126 mem.doNotOptimizeAway(&mac);
127127 }
128 const end = timer.read();
128 const end = benchTime(io);
129129
130130 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
131131 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
......@@ -135,7 +135,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
135135
136136const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }};
137137
138pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 {
138pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int, io: Io) !u64 {
139139 std.debug.assert(DhKeyExchange.shared_length >= DhKeyExchange.secret_length);
140140
141141 var secret: [DhKeyExchange.shared_length]u8 = undefined;
......@@ -144,8 +144,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
144144 var public: [DhKeyExchange.shared_length]u8 = undefined;
145145 random.bytes(public[0..]);
146146
147 var timer = try Timer.start();
148 const start = timer.lap();
147 const start = benchTime(io);
149148 {
150149 var i: usize = 0;
151150 while (i < exchange_count) : (i += 1) {
......@@ -155,7 +154,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
155154 mem.doNotOptimizeAway(&out);
156155 }
157156 }
158 const end = timer.read();
157 const end = benchTime(io);
159158
160159 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
161160 const throughput = @as(u64, @intFromFloat(exchange_count / elapsed_s));
......@@ -177,8 +176,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count
177176 const msg = [_]u8{0} ** 64;
178177 const key_pair = Signature.KeyPair.generate(io);
179178
180 var timer = try Timer.start();
181 const start = timer.lap();
179 const start = benchTime(io);
182180 {
183181 var i: usize = 0;
184182 while (i < signatures_count) : (i += 1) {
......@@ -186,7 +184,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count
186184 mem.doNotOptimizeAway(&sig);
187185 }
188186 }
189 const end = timer.read();
187 const end = benchTime(io);
190188
191189 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
192190 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
......@@ -206,8 +204,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign
206204 const key_pair = Signature.KeyPair.generate(io);
207205 const sig = try key_pair.sign(&msg, null);
208206
209 var timer = try Timer.start();
210 const start = timer.lap();
207 const start = benchTime(io);
211208 {
212209 var i: usize = 0;
213210 while (i < signatures_count) : (i += 1) {
......@@ -215,7 +212,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign
215212 mem.doNotOptimizeAway(&sig);
216213 }
217214 }
218 const end = timer.read();
215 const end = benchTime(io);
219216
220217 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
221218 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
......@@ -235,8 +232,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime
235232 element.* = Signature.BatchElement{ .sig = sig, .msg = &msg, .public_key = key_pair.public_key };
236233 }
237234
238 var timer = try Timer.start();
239 const start = timer.lap();
235 const start = benchTime(io);
240236 {
241237 var i: usize = 0;
242238 while (i < signatures_count) : (i += 1) {
......@@ -244,7 +240,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime
244240 mem.doNotOptimizeAway(&sig);
245241 }
246242 }
247 const end = timer.read();
243 const end = benchTime(io);
248244
249245 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
250246 const throughput = batch.len * @as(u64, @intFromFloat(signatures_count / elapsed_s));
......@@ -261,8 +257,7 @@ const kems = [_]Crypto{
261257pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {
262258 const key_pair = Kem.KeyPair.generate(io);
263259
264 var timer = try Timer.start();
265 const start = timer.lap();
260 const start = benchTime(io);
266261 {
267262 var i: usize = 0;
268263 while (i < kems_count) : (i += 1) {
......@@ -270,7 +265,7 @@ pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io
270265 mem.doNotOptimizeAway(&e);
271266 }
272267 }
273 const end = timer.read();
268 const end = benchTime(io);
274269
275270 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
276271 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
......@@ -283,8 +278,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
283278
284279 const e = key_pair.public_key.encaps(io);
285280
286 var timer = try Timer.start();
287 const start = timer.lap();
281 const start = benchTime(io);
288282 {
289283 var i: usize = 0;
290284 while (i < kems_count) : (i += 1) {
......@@ -292,7 +286,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
292286 mem.doNotOptimizeAway(&ss2);
293287 }
294288 }
295 const end = timer.read();
289 const end = benchTime(io);
296290
297291 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
298292 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
......@@ -301,8 +295,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
301295}
302296
303297pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {
304 var timer = try Timer.start();
305 const start = timer.lap();
298 const start = benchTime(io);
306299 {
307300 var i: usize = 0;
308301 while (i < kems_count) : (i += 1) {
......@@ -310,7 +303,7 @@ pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_i
310303 mem.doNotOptimizeAway(&key_pair);
311304 }
312305 }
313 const end = timer.read();
306 const end = benchTime(io);
314307
315308 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
316309 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
......@@ -337,7 +330,7 @@ const aeads = [_]Crypto{
337330 Crypto{ .ty = crypto.aead.isap.IsapA128A, .name = "isapa128a" },
338331};
339332
340pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 {
333pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int, io: Io) !u64 {
341334 var in: [512 * KiB]u8 = undefined;
342335 random.bytes(in[0..]);
343336
......@@ -350,14 +343,13 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64
350343 random.bytes(nonce[0..]);
351344
352345 var offset: usize = 0;
353 var timer = try Timer.start();
354 const start = timer.lap();
346 const start = benchTime(io);
355347 while (offset < bytes) : (offset += in.len) {
356348 Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key);
357349 try Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key);
358350 }
359351 mem.doNotOptimizeAway(&in);
360 const end = timer.read();
352 const end = benchTime(io);
361353
362354 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
363355 const throughput = @as(u64, @intFromFloat(2 * bytes / elapsed_s));
......@@ -370,15 +362,14 @@ const aes = [_]Crypto{
370362 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-single" },
371363};
372364
373pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int) !u64 {
365pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int, io: Io) !u64 {
374366 var key: [Aes.key_bits / 8]u8 = undefined;
375367 random.bytes(key[0..]);
376368 const ctx = Aes.initEnc(key);
377369
378370 var in = [_]u8{0} ** 16;
379371
380 var timer = try Timer.start();
381 const start = timer.lap();
372 const start = benchTime(io);
382373 {
383374 var i: usize = 0;
384375 while (i < count) : (i += 1) {
......@@ -386,7 +377,7 @@ pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int) !u64 {
386377 }
387378 }
388379 mem.doNotOptimizeAway(&in);
389 const end = timer.read();
380 const end = benchTime(io);
390381
391382 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
392383 const throughput = @as(u64, @intFromFloat(count / elapsed_s));
......@@ -399,15 +390,14 @@ const aes8 = [_]Crypto{
399390 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-8" },
400391};
401392
402pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int) !u64 {
393pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int, io: Io) !u64 {
403394 var key: [Aes.key_bits / 8]u8 = undefined;
404395 random.bytes(key[0..]);
405396 const ctx = Aes.initEnc(key);
406397
407398 var in = [_]u8{0} ** (8 * 16);
408399
409 var timer = try Timer.start();
410 const start = timer.lap();
400 const start = benchTime(io);
411401 {
412402 var i: usize = 0;
413403 while (i < count) : (i += 1) {
......@@ -415,7 +405,7 @@ pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int) !u64 {
415405 }
416406 }
417407 mem.doNotOptimizeAway(&in);
418 const end = timer.read();
408 const end = benchTime(io);
419409
420410 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
421411 const throughput = @as(u64, @intFromFloat(8 * count / elapsed_s));
......@@ -468,8 +458,7 @@ fn benchmarkPwhash(
468458 const needs_salt = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type != std.Io;
469459 const salt: [16]u8 = .{0} ** 16;
470460
471 var timer = try Timer.start();
472 const start = timer.lap();
461 const start = benchTime(io);
473462 {
474463 var i: usize = 0;
475464 while (i < count) : (i += 1) {
......@@ -483,7 +472,7 @@ fn benchmarkPwhash(
483472 mem.doNotOptimizeAway(&buf);
484473 }
485474 }
486 const end = timer.read();
475 const end = benchTime(io);
487476
488477 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
489478 const throughput = elapsed_s / count;
......@@ -554,7 +543,7 @@ pub fn main(init: std.process.Init) !void {
554543
555544 inline for (hashes) |H| {
556545 if (filter == null or std.mem.find(u8, H.name, filter.?) != null) {
557 const throughput = try benchmarkHash(H.ty, mode(128 * MiB));
546 const throughput = try benchmarkHash(H.ty, mode(128 * MiB), io);
558547 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });
559548 try stdout.flush();
560549 }
......@@ -570,7 +559,7 @@ pub fn main(init: std.process.Init) !void {
570559
571560 inline for (macs) |M| {
572561 if (filter == null or std.mem.find(u8, M.name, filter.?) != null) {
573 const throughput = try benchmarkMac(M.ty, mode(128 * MiB));
562 const throughput = try benchmarkMac(M.ty, mode(128 * MiB), io);
574563 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ M.name, throughput / (1 * MiB) });
575564 try stdout.flush();
576565 }
......@@ -578,7 +567,7 @@ pub fn main(init: std.process.Init) !void {
578567
579568 inline for (exchanges) |E| {
580569 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
581 const throughput = try benchmarkKeyExchange(E.ty, mode(1000));
570 const throughput = try benchmarkKeyExchange(E.ty, mode(1000), io);
582571 try stdout.print("{s:>17}: {:10} exchanges/s\n", .{ E.name, throughput });
583572 try stdout.flush();
584573 }
......@@ -610,7 +599,7 @@ pub fn main(init: std.process.Init) !void {
610599
611600 inline for (aeads) |E| {
612601 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
613 const throughput = try benchmarkAead(E.ty, mode(128 * MiB));
602 const throughput = try benchmarkAead(E.ty, mode(128 * MiB), io);
614603 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ E.name, throughput / (1 * MiB) });
615604 try stdout.flush();
616605 }
......@@ -618,7 +607,7 @@ pub fn main(init: std.process.Init) !void {
618607
619608 inline for (aes) |E| {
620609 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
621 const throughput = try benchmarkAes(E.ty, mode(100000000));
610 const throughput = try benchmarkAes(E.ty, mode(100000000), io);
622611 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
623612 try stdout.flush();
624613 }
......@@ -626,7 +615,7 @@ pub fn main(init: std.process.Init) !void {
626615
627616 inline for (aes8) |E| {
628617 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
629 const throughput = try benchmarkAes8(E.ty, mode(10000000));
618 const throughput = try benchmarkAes8(E.ty, mode(10000000), io);
630619 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
631620 try stdout.flush();
632621 }
lib/std/hash/benchmark.zig+26-21
......@@ -4,7 +4,6 @@ const builtin = @import("builtin");
44const std = @import("std");
55const Io = std.Io;
66const time = std.time;
7const Timer = time.Timer;
87const hash = std.hash;
98
109const KiB = 1024;
......@@ -111,7 +110,11 @@ const Result = struct {
111110
112111const block_size: usize = 8 * 8192;
113112
114pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Allocator) !Result {
113pub fn benchTime(io: Io) i96 {
114 return Io.Clock.awake.now(io).nanoseconds;
115}
116
117pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Allocator, io: Io) !Result {
115118 var blocks = try allocator.alloc(u8, bytes);
116119 defer allocator.free(blocks);
117120 random.bytes(blocks);
......@@ -131,7 +134,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
131134 break :blk .init();
132135 };
133136
134 var timer = try Timer.start();
137 const start = benchTime(io);
135138 for (0..block_count) |i| {
136139 h.update(blocks[i * block_size ..][0..block_size]);
137140 }
......@@ -143,7 +146,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
143146 h.final();
144147 std.mem.doNotOptimizeAway(final);
145148
146 const elapsed_ns = timer.read();
149 const elapsed_ns = benchTime(io) - start;
147150
148151 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
149152 const size_float: f64 = @floatFromInt(block_size * block_count);
......@@ -155,14 +158,14 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
155158 };
156159}
157160
158pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator) !Result {
161pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator, io: Io) !Result {
159162 var blocks = try allocator.alloc(u8, bytes);
160163 defer allocator.free(blocks);
161164 random.bytes(blocks);
162165
163166 const key_count = bytes / key_size;
164167
165 var timer = try Timer.start();
168 const start = benchTime(io);
166169
167170 var sum: u64 = 0;
168171 for (0..key_count) |i| {
......@@ -182,7 +185,7 @@ pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize
182185 };
183186 sum +%= final;
184187 }
185 const elapsed_ns = timer.read();
188 const elapsed_ns = benchTime(io) - start;
186189
187190 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
188191 const size_float: f64 = @floatFromInt(key_count * key_size);
......@@ -204,6 +207,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
204207 comptime key_size: usize,
205208 bytes: usize,
206209 allocator: std.mem.Allocator,
210 io: Io,
207211) !Result {
208212 var blocks = try allocator.alloc(u8, bytes);
209213 defer allocator.free(blocks);
......@@ -211,7 +215,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
211215
212216 const key_count = bytes / key_size;
213217
214 var timer = try Timer.start();
218 const start = benchTime(io);
215219
216220 var sum: u64 = 0;
217221 for (0..key_count) |i| {
......@@ -231,7 +235,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
231235 };
232236 sum +%= final;
233237 }
234 const elapsed_ns = timer.read();
238 const elapsed_ns = benchTime(io) - start;
235239
236240 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
237241 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
......@@ -252,6 +256,7 @@ pub fn benchmarkHashSmallKeysArray(
252256 comptime key_size: usize,
253257 bytes: usize,
254258 allocator: std.mem.Allocator,
259 io: Io,
255260) !Result {
256261 var blocks = try allocator.alloc(u8, bytes);
257262 defer allocator.free(blocks);
......@@ -260,7 +265,7 @@ pub fn benchmarkHashSmallKeysArray(
260265 const key_count = bytes / key_size;
261266
262267 var i: usize = 0;
263 var timer = try Timer.start();
268 const start = benchTime(io);
264269
265270 var sum: u64 = 0;
266271 while (i < key_count) : (i += 1) {
......@@ -280,7 +285,7 @@ pub fn benchmarkHashSmallKeysArray(
280285 };
281286 sum +%= final;
282287 }
283 const elapsed_ns = timer.read();
288 const elapsed_ns = benchTime(io) - start;
284289
285290 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
286291 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
......@@ -293,14 +298,14 @@ pub fn benchmarkHashSmallKeysArray(
293298 };
294299}
295300
296pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator) !Result {
301pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator, io: Io) !Result {
297302 var blocks = try allocator.alloc(u8, bytes);
298303 defer allocator.free(blocks);
299304 random.bytes(blocks);
300305
301306 const key_count = bytes / key_size;
302307
303 var timer = try Timer.start();
308 const start = benchTime(io);
304309
305310 var sum: u64 = 0;
306311 for (0..key_count) |i| {
......@@ -320,7 +325,7 @@ pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize,
320325 };
321326 sum +%= final;
322327 }
323 const elapsed_ns = timer.read();
328 const elapsed_ns = benchTime(io) - start;
324329
325330 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
326331 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
......@@ -454,7 +459,7 @@ pub fn main(init: std.process.Init) !void {
454459 // This allows easier comparison between different implementations.
455460 if (H.has_iterative_api and !test_small_key_only) {
456461 prng.seed(seed);
457 const result = try benchmarkHash(H, count, allocator);
462 const result = try benchmarkHash(H, count, allocator, io);
458463 try stdout.print(" iterative: {:5} MiB/s [{x:0<16}]\n", .{ result.throughput / (1 * MiB), result.hash });
459464 try stdout.flush();
460465 }
......@@ -462,7 +467,7 @@ pub fn main(init: std.process.Init) !void {
462467 if (!test_iterative_only) {
463468 if (key_size) |size| {
464469 prng.seed(seed);
465 const result_small = try benchmarkHashSmallKeys(H, size, count, allocator);
470 const result_small = try benchmarkHashSmallKeys(H, size, count, allocator, io);
466471 try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{
467472 size,
468473 result_small.throughput / (1 * MiB),
......@@ -476,9 +481,9 @@ pub fn main(init: std.process.Init) !void {
476481 inline for (sizes) |exact_size| {
477482 if (size == exact_size) {
478483 prng.seed(seed);
479 const result_array = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator);
484 const result_array = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator, io);
480485 prng.seed(seed);
481 const result_ptr = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator);
486 const result_ptr = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator, io);
482487 try stdout.print(" array: {:5} MiB/s [{x:0<16}]\n", .{
483488 result_array.throughput / (1 * MiB),
484489 result_array.hash,
......@@ -493,7 +498,7 @@ pub fn main(init: std.process.Init) !void {
493498 }
494499 } else {
495500 prng.seed(seed);
496 const result_small = try benchmarkHashSmallKeys(H, default_small_key_size, count, allocator);
501 const result_small = try benchmarkHashSmallKeys(H, default_small_key_size, count, allocator, io);
497502 try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{
498503 default_small_key_size,
499504 result_small.throughput / (1 * MiB),
......@@ -507,7 +512,7 @@ pub fn main(init: std.process.Init) !void {
507512 try stdout.print(" array:\n", .{});
508513 inline for (sizes) |exact_size| {
509514 prng.seed(seed);
510 const result = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator);
515 const result = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator, io);
511516 try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{
512517 exact_size,
513518 result.throughput / (1 * MiB),
......@@ -518,7 +523,7 @@ pub fn main(init: std.process.Init) !void {
518523 try stdout.print(" array ptr: \n", .{});
519524 inline for (sizes) |exact_size| {
520525 prng.seed(seed);
521 const result = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator);
526 const result = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator, io);
522527 try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{
523528 exact_size,
524529 result.throughput / (1 * MiB),
lib/std/unicode/throughput_test.zig+14-12
......@@ -2,7 +2,6 @@ const std = @import("std");
22const Io = std.Io;
33const time = std.time;
44const unicode = std.unicode;
5const Timer = std.time.Timer;
65
76const N = 1_000_000;
87
......@@ -15,12 +14,14 @@ const ResultCount = struct {
1514 throughput: u64,
1615};
1716
18fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
19 var timer = try Timer.start();
17fn benchTime(io: Io) i96 {
18 return Io.Clock.awake.now(io).nanoseconds;
19}
2020
21fn benchmarkCodepointCount(buf: []const u8, io: Io) !ResultCount {
2122 const bytes = N * buf.len;
2223
23 const start = timer.lap();
24 const start = benchTime(io);
2425 var i: usize = 0;
2526 var r: usize = undefined;
2627 while (i < N) : (i += 1) {
......@@ -30,7 +31,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
3031 .{buf},
3132 );
3233 }
33 const end = timer.read();
34 const end = benchTime(io);
3435
3536 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
3637 const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));
......@@ -38,44 +39,45 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
3839 return ResultCount{ .count = r, .throughput = throughput };
3940}
4041
41pub fn main() !void {
42pub fn main(init: std.process.Init) !void {
4243 // Size of buffer is about size of printed message.
44 const io = init.io;
4345 var stdout_buffer: [0x100]u8 = undefined;
44 var stdout_writer = Io.File.stdout().writer(&stdout_buffer);
46 var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
4547 const stdout = &stdout_writer.interface;
4648
4749 try stdout.print("short ASCII strings\n", .{});
4850 try stdout.flush();
4951 {
50 const result = try benchmarkCodepointCount("abc");
52 const result = try benchmarkCodepointCount("abc", io);
5153 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
5254 }
5355
5456 try stdout.print("short Unicode strings\n", .{});
5557 try stdout.flush();
5658 {
57 const result = try benchmarkCodepointCount("ŌŌŌ");
59 const result = try benchmarkCodepointCount("ŌŌŌ", io);
5860 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
5961 }
6062
6163 try stdout.print("pure ASCII strings\n", .{});
6264 try stdout.flush();
6365 {
64 const result = try benchmarkCodepointCount("hello" ** 16);
66 const result = try benchmarkCodepointCount("hello" ** 16, io);
6567 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
6668 }
6769
6870 try stdout.print("pure Unicode strings\n", .{});
6971 try stdout.flush();
7072 {
71 const result = try benchmarkCodepointCount("こんにちは" ** 16);
73 const result = try benchmarkCodepointCount("こんにちは" ** 16, io);
7274 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
7375 }
7476
7577 try stdout.print("mixed ASCII/Unicode strings\n", .{});
7678 try stdout.flush();
7779 {
78 const result = try benchmarkCodepointCount("Hyvää huomenta" ** 16);
80 const result = try benchmarkCodepointCount("Hyvää huomenta" ** 16, io);
7981 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
8082 }
8183 try stdout.flush();