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");...@@ -5,7 +5,6 @@ const builtin = @import("builtin");
5const std = @import("std");5const std = @import("std");
6const Io = std.Io;6const Io = std.Io;
7const time = std.time;7const time = std.time;
8const Timer = time.Timer;
9const Random = std.Random;8const Random = std.Random;
109
11const KiB = 1024;10const KiB = 1024;
...@@ -72,7 +71,11 @@ const Result = struct {...@@ -72,7 +71,11 @@ const Result = struct {
72const long_block_size: usize = 8 * 8192;71const long_block_size: usize = 8 * 8192;
73const short_block_size: usize = 8;72const 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 {
76 var rng = blk: {79 var rng = blk: {
77 if (H.init_u8s) |init| {80 if (H.init_u8s) |init| {
78 break :blk H.ty.init(init[0..].*);81 break :blk H.ty.init(init[0..].*);
...@@ -86,12 +89,11 @@ pub fn benchmark(comptime H: anytype, bytes: usize, comptime block_size: usize)...@@ -86,12 +89,11 @@ pub fn benchmark(comptime H: anytype, bytes: usize, comptime block_size: usize)
86 var block: [block_size]u8 = undefined;89 var block: [block_size]u8 = undefined;
8790
88 var offset: usize = 0;91 var offset: usize = 0;
89 var timer = try Timer.start();92 const start = benchTime(io);
90 const start = timer.lap();
91 while (offset < bytes) : (offset += block.len) {93 while (offset < bytes) : (offset += block.len) {
92 rng.fill(block[0..]);94 rng.fill(block[0..]);
93 }95 }
94 const end = timer.read();96 const end = benchTime(io);
9597
96 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;98 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
97 const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));99 const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));
...@@ -187,7 +189,7 @@ pub fn main(init: std.process.Init) !void {...@@ -187,7 +189,7 @@ pub fn main(init: std.process.Init) !void {
187 try stdout.print("{s} (long outputs)\n", .{R.name});189 try stdout.print("{s} (long outputs)\n", .{R.name});
188 try stdout.flush();190 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);
191 try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});193 try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
192 }194 }
193 }195 }
...@@ -198,7 +200,7 @@ pub fn main(init: std.process.Init) !void {...@@ -198,7 +200,7 @@ pub fn main(init: std.process.Init) !void {
198 try stdout.print("{s} (short outputs)\n", .{R.name});200 try stdout.print("{s} (short outputs)\n", .{R.name});
199 try stdout.flush();201 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);
202 try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});204 try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
203 }205 }
204 }206 }
...@@ -211,7 +213,7 @@ pub fn main(init: std.process.Init) !void {...@@ -211,7 +213,7 @@ pub fn main(init: std.process.Init) !void {
211 try stdout.print("{s} (cryptographic, long outputs)\n", .{R.name});213 try stdout.print("{s} (cryptographic, long outputs)\n", .{R.name});
212 try stdout.flush();214 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);
215 try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});217 try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
216 }218 }
217 }219 }
...@@ -222,7 +224,7 @@ pub fn main(init: std.process.Init) !void {...@@ -222,7 +224,7 @@ pub fn main(init: std.process.Init) !void {
222 try stdout.print("{s} (cryptographic, short outputs)\n", .{R.name});224 try stdout.print("{s} (cryptographic, short outputs)\n", .{R.name});
223 try stdout.flush();225 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);
226 try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});228 try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
227 }229 }
228 }230 }
lib/std/crypto/benchmark.zig+44-55
...@@ -6,7 +6,6 @@ const std = @import("std");...@@ -6,7 +6,6 @@ const std = @import("std");
6const Io = std.Io;6const Io = std.Io;
7const mem = std.mem;7const mem = std.mem;
8const time = std.time;8const time = std.time;
9const Timer = std.time.Timer;
10const crypto = std.crypto;9const crypto = std.crypto;
1110
12const KiB = 1024;11const KiB = 1024;
...@@ -45,15 +44,18 @@ const parallel_hashes = [_]Crypto{...@@ -45,15 +44,18 @@ const parallel_hashes = [_]Crypto{
4544
46const block_size: usize = 8 * 8192;45const 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 {
49 const blocks_count = bytes / block_size;52 const blocks_count = bytes / block_size;
50 var block: [block_size]u8 = undefined;53 var block: [block_size]u8 = undefined;
51 random.bytes(&block);54 random.bytes(&block);
5255
53 var h = Hash.init(.{});56 var h = Hash.init(.{});
5457
55 var timer = try Timer.start();58 const start = benchTime(io);
56 const start = timer.lap();
57 for (0..blocks_count) |_| {59 for (0..blocks_count) |_| {
58 h.update(&block);60 h.update(&block);
59 }61 }
...@@ -61,7 +63,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64...@@ -61,7 +63,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
61 h.final(&final);63 h.final(&final);
62 std.mem.doNotOptimizeAway(final);64 std.mem.doNotOptimizeAway(final);
6365
64 const end = timer.read();66 const end = benchTime(io);
6567
66 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;68 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
67 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));69 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
...@@ -74,13 +76,12 @@ pub fn benchmarkHashParallel(comptime Hash: anytype, comptime bytes: comptime_in...@@ -74,13 +76,12 @@ pub fn benchmarkHashParallel(comptime Hash: anytype, comptime bytes: comptime_in
74 defer allocator.free(data);76 defer allocator.free(data);
75 random.bytes(data);77 random.bytes(data);
7678
77 var timer = try Timer.start();79 const start = benchTime(io);
78 const start = timer.lap();
79 var final: [Hash.digest_length]u8 = undefined;80 var final: [Hash.digest_length]u8 = undefined;
80 try Hash.hashParallel(data, &final, .{}, allocator, io);81 try Hash.hashParallel(data, &final, .{}, allocator, io);
81 std.mem.doNotOptimizeAway(final);82 std.mem.doNotOptimizeAway(final);
8283
83 const end = timer.read();84 const end = benchTime(io);
8485
85 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;86 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
86 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));87 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
...@@ -109,7 +110,7 @@ const macs = [_]Crypto{...@@ -109,7 +110,7 @@ const macs = [_]Crypto{
109 Crypto{ .ty = crypto.auth.cmac.CmacAes128, .name = "aes-cmac" },110 Crypto{ .ty = crypto.auth.cmac.CmacAes128, .name = "aes-cmac" },
110};111};
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 {
113 var in: [512 * KiB]u8 = undefined;114 var in: [512 * KiB]u8 = undefined;
114 random.bytes(in[0..]);115 random.bytes(in[0..]);
115116
...@@ -119,13 +120,12 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {...@@ -119,13 +120,12 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
119120
120 var mac: [Mac.mac_length]u8 = undefined;121 var mac: [Mac.mac_length]u8 = undefined;
121 var offset: usize = 0;122 var offset: usize = 0;
122 var timer = try Timer.start();123 const start = benchTime(io);
123 const start = timer.lap();
124 while (offset < bytes) : (offset += in.len) {124 while (offset < bytes) : (offset += in.len) {
125 Mac.create(mac[0..], in[0..], key[0..]);125 Mac.create(mac[0..], in[0..], key[0..]);
126 mem.doNotOptimizeAway(&mac);126 mem.doNotOptimizeAway(&mac);
127 }127 }
128 const end = timer.read();128 const end = benchTime(io);
129129
130 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;130 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
131 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));131 const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
...@@ -135,7 +135,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {...@@ -135,7 +135,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
135135
136const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }};136const 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 {
139 std.debug.assert(DhKeyExchange.shared_length >= DhKeyExchange.secret_length);139 std.debug.assert(DhKeyExchange.shared_length >= DhKeyExchange.secret_length);
140140
141 var secret: [DhKeyExchange.shared_length]u8 = undefined;141 var secret: [DhKeyExchange.shared_length]u8 = undefined;
...@@ -144,8 +144,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c...@@ -144,8 +144,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
144 var public: [DhKeyExchange.shared_length]u8 = undefined;144 var public: [DhKeyExchange.shared_length]u8 = undefined;
145 random.bytes(public[0..]);145 random.bytes(public[0..]);
146146
147 var timer = try Timer.start();147 const start = benchTime(io);
148 const start = timer.lap();
149 {148 {
150 var i: usize = 0;149 var i: usize = 0;
151 while (i < exchange_count) : (i += 1) {150 while (i < exchange_count) : (i += 1) {
...@@ -155,7 +154,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c...@@ -155,7 +154,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
155 mem.doNotOptimizeAway(&out);154 mem.doNotOptimizeAway(&out);
156 }155 }
157 }156 }
158 const end = timer.read();157 const end = benchTime(io);
159158
160 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;159 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
161 const throughput = @as(u64, @intFromFloat(exchange_count / elapsed_s));160 const throughput = @as(u64, @intFromFloat(exchange_count / elapsed_s));
...@@ -177,8 +176,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count...@@ -177,8 +176,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count
177 const msg = [_]u8{0} ** 64;176 const msg = [_]u8{0} ** 64;
178 const key_pair = Signature.KeyPair.generate(io);177 const key_pair = Signature.KeyPair.generate(io);
179178
180 var timer = try Timer.start();179 const start = benchTime(io);
181 const start = timer.lap();
182 {180 {
183 var i: usize = 0;181 var i: usize = 0;
184 while (i < signatures_count) : (i += 1) {182 while (i < signatures_count) : (i += 1) {
...@@ -186,7 +184,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count...@@ -186,7 +184,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count
186 mem.doNotOptimizeAway(&sig);184 mem.doNotOptimizeAway(&sig);
187 }185 }
188 }186 }
189 const end = timer.read();187 const end = benchTime(io);
190188
191 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;189 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
192 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));190 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
...@@ -206,8 +204,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign...@@ -206,8 +204,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign
206 const key_pair = Signature.KeyPair.generate(io);204 const key_pair = Signature.KeyPair.generate(io);
207 const sig = try key_pair.sign(&msg, null);205 const sig = try key_pair.sign(&msg, null);
208206
209 var timer = try Timer.start();207 const start = benchTime(io);
210 const start = timer.lap();
211 {208 {
212 var i: usize = 0;209 var i: usize = 0;
213 while (i < signatures_count) : (i += 1) {210 while (i < signatures_count) : (i += 1) {
...@@ -215,7 +212,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign...@@ -215,7 +212,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign
215 mem.doNotOptimizeAway(&sig);212 mem.doNotOptimizeAway(&sig);
216 }213 }
217 }214 }
218 const end = timer.read();215 const end = benchTime(io);
219216
220 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;217 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
221 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));218 const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
...@@ -235,8 +232,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime...@@ -235,8 +232,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime
235 element.* = Signature.BatchElement{ .sig = sig, .msg = &msg, .public_key = key_pair.public_key };232 element.* = Signature.BatchElement{ .sig = sig, .msg = &msg, .public_key = key_pair.public_key };
236 }233 }
237234
238 var timer = try Timer.start();235 const start = benchTime(io);
239 const start = timer.lap();
240 {236 {
241 var i: usize = 0;237 var i: usize = 0;
242 while (i < signatures_count) : (i += 1) {238 while (i < signatures_count) : (i += 1) {
...@@ -244,7 +240,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime...@@ -244,7 +240,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime
244 mem.doNotOptimizeAway(&sig);240 mem.doNotOptimizeAway(&sig);
245 }241 }
246 }242 }
247 const end = timer.read();243 const end = benchTime(io);
248244
249 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;245 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
250 const throughput = batch.len * @as(u64, @intFromFloat(signatures_count / elapsed_s));246 const throughput = batch.len * @as(u64, @intFromFloat(signatures_count / elapsed_s));
...@@ -261,8 +257,7 @@ const kems = [_]Crypto{...@@ -261,8 +257,7 @@ const kems = [_]Crypto{
261pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {257pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {
262 const key_pair = Kem.KeyPair.generate(io);258 const key_pair = Kem.KeyPair.generate(io);
263259
264 var timer = try Timer.start();260 const start = benchTime(io);
265 const start = timer.lap();
266 {261 {
267 var i: usize = 0;262 var i: usize = 0;
268 while (i < kems_count) : (i += 1) {263 while (i < kems_count) : (i += 1) {
...@@ -270,7 +265,7 @@ pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io...@@ -270,7 +265,7 @@ pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io
270 mem.doNotOptimizeAway(&e);265 mem.doNotOptimizeAway(&e);
271 }266 }
272 }267 }
273 const end = timer.read();268 const end = benchTime(io);
274269
275 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;270 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
276 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));271 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
...@@ -283,8 +278,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i...@@ -283,8 +278,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
283278
284 const e = key_pair.public_key.encaps(io);279 const e = key_pair.public_key.encaps(io);
285280
286 var timer = try Timer.start();281 const start = benchTime(io);
287 const start = timer.lap();
288 {282 {
289 var i: usize = 0;283 var i: usize = 0;
290 while (i < kems_count) : (i += 1) {284 while (i < kems_count) : (i += 1) {
...@@ -292,7 +286,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i...@@ -292,7 +286,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
292 mem.doNotOptimizeAway(&ss2);286 mem.doNotOptimizeAway(&ss2);
293 }287 }
294 }288 }
295 const end = timer.read();289 const end = benchTime(io);
296290
297 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;291 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
298 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));292 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
...@@ -301,8 +295,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i...@@ -301,8 +295,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
301}295}
302296
303pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {297pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {
304 var timer = try Timer.start();298 const start = benchTime(io);
305 const start = timer.lap();
306 {299 {
307 var i: usize = 0;300 var i: usize = 0;
308 while (i < kems_count) : (i += 1) {301 while (i < kems_count) : (i += 1) {
...@@ -310,7 +303,7 @@ pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_i...@@ -310,7 +303,7 @@ pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_i
310 mem.doNotOptimizeAway(&key_pair);303 mem.doNotOptimizeAway(&key_pair);
311 }304 }
312 }305 }
313 const end = timer.read();306 const end = benchTime(io);
314307
315 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;308 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
316 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));309 const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
...@@ -337,7 +330,7 @@ const aeads = [_]Crypto{...@@ -337,7 +330,7 @@ const aeads = [_]Crypto{
337 Crypto{ .ty = crypto.aead.isap.IsapA128A, .name = "isapa128a" },330 Crypto{ .ty = crypto.aead.isap.IsapA128A, .name = "isapa128a" },
338};331};
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 {
341 var in: [512 * KiB]u8 = undefined;334 var in: [512 * KiB]u8 = undefined;
342 random.bytes(in[0..]);335 random.bytes(in[0..]);
343336
...@@ -350,14 +343,13 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64...@@ -350,14 +343,13 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64
350 random.bytes(nonce[0..]);343 random.bytes(nonce[0..]);
351344
352 var offset: usize = 0;345 var offset: usize = 0;
353 var timer = try Timer.start();346 const start = benchTime(io);
354 const start = timer.lap();
355 while (offset < bytes) : (offset += in.len) {347 while (offset < bytes) : (offset += in.len) {
356 Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key);348 Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key);
357 try Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key);349 try Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key);
358 }350 }
359 mem.doNotOptimizeAway(&in);351 mem.doNotOptimizeAway(&in);
360 const end = timer.read();352 const end = benchTime(io);
361353
362 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;354 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
363 const throughput = @as(u64, @intFromFloat(2 * bytes / elapsed_s));355 const throughput = @as(u64, @intFromFloat(2 * bytes / elapsed_s));
...@@ -370,15 +362,14 @@ const aes = [_]Crypto{...@@ -370,15 +362,14 @@ const aes = [_]Crypto{
370 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-single" },362 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-single" },
371};363};
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 {
374 var key: [Aes.key_bits / 8]u8 = undefined;366 var key: [Aes.key_bits / 8]u8 = undefined;
375 random.bytes(key[0..]);367 random.bytes(key[0..]);
376 const ctx = Aes.initEnc(key);368 const ctx = Aes.initEnc(key);
377369
378 var in = [_]u8{0} ** 16;370 var in = [_]u8{0} ** 16;
379371
380 var timer = try Timer.start();372 const start = benchTime(io);
381 const start = timer.lap();
382 {373 {
383 var i: usize = 0;374 var i: usize = 0;
384 while (i < count) : (i += 1) {375 while (i < count) : (i += 1) {
...@@ -386,7 +377,7 @@ pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int) !u64 {...@@ -386,7 +377,7 @@ pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int) !u64 {
386 }377 }
387 }378 }
388 mem.doNotOptimizeAway(&in);379 mem.doNotOptimizeAway(&in);
389 const end = timer.read();380 const end = benchTime(io);
390381
391 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;382 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
392 const throughput = @as(u64, @intFromFloat(count / elapsed_s));383 const throughput = @as(u64, @intFromFloat(count / elapsed_s));
...@@ -399,15 +390,14 @@ const aes8 = [_]Crypto{...@@ -399,15 +390,14 @@ const aes8 = [_]Crypto{
399 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-8" },390 Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-8" },
400};391};
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 {
403 var key: [Aes.key_bits / 8]u8 = undefined;394 var key: [Aes.key_bits / 8]u8 = undefined;
404 random.bytes(key[0..]);395 random.bytes(key[0..]);
405 const ctx = Aes.initEnc(key);396 const ctx = Aes.initEnc(key);
406397
407 var in = [_]u8{0} ** (8 * 16);398 var in = [_]u8{0} ** (8 * 16);
408399
409 var timer = try Timer.start();400 const start = benchTime(io);
410 const start = timer.lap();
411 {401 {
412 var i: usize = 0;402 var i: usize = 0;
413 while (i < count) : (i += 1) {403 while (i < count) : (i += 1) {
...@@ -415,7 +405,7 @@ pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int) !u64 {...@@ -415,7 +405,7 @@ pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int) !u64 {
415 }405 }
416 }406 }
417 mem.doNotOptimizeAway(&in);407 mem.doNotOptimizeAway(&in);
418 const end = timer.read();408 const end = benchTime(io);
419409
420 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;410 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
421 const throughput = @as(u64, @intFromFloat(8 * count / elapsed_s));411 const throughput = @as(u64, @intFromFloat(8 * count / elapsed_s));
...@@ -468,8 +458,7 @@ fn benchmarkPwhash(...@@ -468,8 +458,7 @@ fn benchmarkPwhash(
468 const needs_salt = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type != std.Io;458 const needs_salt = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type != std.Io;
469 const salt: [16]u8 = .{0} ** 16;459 const salt: [16]u8 = .{0} ** 16;
470460
471 var timer = try Timer.start();461 const start = benchTime(io);
472 const start = timer.lap();
473 {462 {
474 var i: usize = 0;463 var i: usize = 0;
475 while (i < count) : (i += 1) {464 while (i < count) : (i += 1) {
...@@ -483,7 +472,7 @@ fn benchmarkPwhash(...@@ -483,7 +472,7 @@ fn benchmarkPwhash(
483 mem.doNotOptimizeAway(&buf);472 mem.doNotOptimizeAway(&buf);
484 }473 }
485 }474 }
486 const end = timer.read();475 const end = benchTime(io);
487476
488 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;477 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
489 const throughput = elapsed_s / count;478 const throughput = elapsed_s / count;
...@@ -554,7 +543,7 @@ pub fn main(init: std.process.Init) !void {...@@ -554,7 +543,7 @@ pub fn main(init: std.process.Init) !void {
554543
555 inline for (hashes) |H| {544 inline for (hashes) |H| {
556 if (filter == null or std.mem.find(u8, H.name, filter.?) != null) {545 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);
558 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });547 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });
559 try stdout.flush();548 try stdout.flush();
560 }549 }
...@@ -570,7 +559,7 @@ pub fn main(init: std.process.Init) !void {...@@ -570,7 +559,7 @@ pub fn main(init: std.process.Init) !void {
570559
571 inline for (macs) |M| {560 inline for (macs) |M| {
572 if (filter == null or std.mem.find(u8, M.name, filter.?) != null) {561 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);
574 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ M.name, throughput / (1 * MiB) });563 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ M.name, throughput / (1 * MiB) });
575 try stdout.flush();564 try stdout.flush();
576 }565 }
...@@ -578,7 +567,7 @@ pub fn main(init: std.process.Init) !void {...@@ -578,7 +567,7 @@ pub fn main(init: std.process.Init) !void {
578567
579 inline for (exchanges) |E| {568 inline for (exchanges) |E| {
580 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {569 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);
582 try stdout.print("{s:>17}: {:10} exchanges/s\n", .{ E.name, throughput });571 try stdout.print("{s:>17}: {:10} exchanges/s\n", .{ E.name, throughput });
583 try stdout.flush();572 try stdout.flush();
584 }573 }
...@@ -610,7 +599,7 @@ pub fn main(init: std.process.Init) !void {...@@ -610,7 +599,7 @@ pub fn main(init: std.process.Init) !void {
610599
611 inline for (aeads) |E| {600 inline for (aeads) |E| {
612 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {601 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);
614 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ E.name, throughput / (1 * MiB) });603 try stdout.print("{s:>17}: {:10} MiB/s\n", .{ E.name, throughput / (1 * MiB) });
615 try stdout.flush();604 try stdout.flush();
616 }605 }
...@@ -618,7 +607,7 @@ pub fn main(init: std.process.Init) !void {...@@ -618,7 +607,7 @@ pub fn main(init: std.process.Init) !void {
618607
619 inline for (aes) |E| {608 inline for (aes) |E| {
620 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {609 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);
622 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });611 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
623 try stdout.flush();612 try stdout.flush();
624 }613 }
...@@ -626,7 +615,7 @@ pub fn main(init: std.process.Init) !void {...@@ -626,7 +615,7 @@ pub fn main(init: std.process.Init) !void {
626615
627 inline for (aes8) |E| {616 inline for (aes8) |E| {
628 if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {617 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);
630 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });619 try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
631 try stdout.flush();620 try stdout.flush();
632 }621 }
lib/std/hash/benchmark.zig+26-21
...@@ -4,7 +4,6 @@ const builtin = @import("builtin");...@@ -4,7 +4,6 @@ const builtin = @import("builtin");
4const std = @import("std");4const std = @import("std");
5const Io = std.Io;5const Io = std.Io;
6const time = std.time;6const time = std.time;
7const Timer = time.Timer;
8const hash = std.hash;7const hash = std.hash;
98
10const KiB = 1024;9const KiB = 1024;
...@@ -111,7 +110,11 @@ const Result = struct {...@@ -111,7 +110,11 @@ const Result = struct {
111110
112const block_size: usize = 8 * 8192;111const 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 {
115 var blocks = try allocator.alloc(u8, bytes);118 var blocks = try allocator.alloc(u8, bytes);
116 defer allocator.free(blocks);119 defer allocator.free(blocks);
117 random.bytes(blocks);120 random.bytes(blocks);
...@@ -131,7 +134,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc...@@ -131,7 +134,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
131 break :blk .init();134 break :blk .init();
132 };135 };
133136
134 var timer = try Timer.start();137 const start = benchTime(io);
135 for (0..block_count) |i| {138 for (0..block_count) |i| {
136 h.update(blocks[i * block_size ..][0..block_size]);139 h.update(blocks[i * block_size ..][0..block_size]);
137 }140 }
...@@ -143,7 +146,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc...@@ -143,7 +146,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
143 h.final();146 h.final();
144 std.mem.doNotOptimizeAway(final);147 std.mem.doNotOptimizeAway(final);
145148
146 const elapsed_ns = timer.read();149 const elapsed_ns = benchTime(io) - start;
147150
148 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;151 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
149 const size_float: f64 = @floatFromInt(block_size * block_count);152 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...@@ -155,14 +158,14 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
155 };158 };
156}159}
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 {
159 var blocks = try allocator.alloc(u8, bytes);162 var blocks = try allocator.alloc(u8, bytes);
160 defer allocator.free(blocks);163 defer allocator.free(blocks);
161 random.bytes(blocks);164 random.bytes(blocks);
162165
163 const key_count = bytes / key_size;166 const key_count = bytes / key_size;
164167
165 var timer = try Timer.start();168 const start = benchTime(io);
166169
167 var sum: u64 = 0;170 var sum: u64 = 0;
168 for (0..key_count) |i| {171 for (0..key_count) |i| {
...@@ -182,7 +185,7 @@ pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize...@@ -182,7 +185,7 @@ pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize
182 };185 };
183 sum +%= final;186 sum +%= final;
184 }187 }
185 const elapsed_ns = timer.read();188 const elapsed_ns = benchTime(io) - start;
186189
187 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;190 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
188 const size_float: f64 = @floatFromInt(key_count * key_size);191 const size_float: f64 = @floatFromInt(key_count * key_size);
...@@ -204,6 +207,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(...@@ -204,6 +207,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
204 comptime key_size: usize,207 comptime key_size: usize,
205 bytes: usize,208 bytes: usize,
206 allocator: std.mem.Allocator,209 allocator: std.mem.Allocator,
210 io: Io,
207) !Result {211) !Result {
208 var blocks = try allocator.alloc(u8, bytes);212 var blocks = try allocator.alloc(u8, bytes);
209 defer allocator.free(blocks);213 defer allocator.free(blocks);
...@@ -211,7 +215,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(...@@ -211,7 +215,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
211215
212 const key_count = bytes / key_size;216 const key_count = bytes / key_size;
213217
214 var timer = try Timer.start();218 const start = benchTime(io);
215219
216 var sum: u64 = 0;220 var sum: u64 = 0;
217 for (0..key_count) |i| {221 for (0..key_count) |i| {
...@@ -231,7 +235,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(...@@ -231,7 +235,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
231 };235 };
232 sum +%= final;236 sum +%= final;
233 }237 }
234 const elapsed_ns = timer.read();238 const elapsed_ns = benchTime(io) - start;
235239
236 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;240 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
237 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);241 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
...@@ -252,6 +256,7 @@ pub fn benchmarkHashSmallKeysArray(...@@ -252,6 +256,7 @@ pub fn benchmarkHashSmallKeysArray(
252 comptime key_size: usize,256 comptime key_size: usize,
253 bytes: usize,257 bytes: usize,
254 allocator: std.mem.Allocator,258 allocator: std.mem.Allocator,
259 io: Io,
255) !Result {260) !Result {
256 var blocks = try allocator.alloc(u8, bytes);261 var blocks = try allocator.alloc(u8, bytes);
257 defer allocator.free(blocks);262 defer allocator.free(blocks);
...@@ -260,7 +265,7 @@ pub fn benchmarkHashSmallKeysArray(...@@ -260,7 +265,7 @@ pub fn benchmarkHashSmallKeysArray(
260 const key_count = bytes / key_size;265 const key_count = bytes / key_size;
261266
262 var i: usize = 0;267 var i: usize = 0;
263 var timer = try Timer.start();268 const start = benchTime(io);
264269
265 var sum: u64 = 0;270 var sum: u64 = 0;
266 while (i < key_count) : (i += 1) {271 while (i < key_count) : (i += 1) {
...@@ -280,7 +285,7 @@ pub fn benchmarkHashSmallKeysArray(...@@ -280,7 +285,7 @@ pub fn benchmarkHashSmallKeysArray(
280 };285 };
281 sum +%= final;286 sum +%= final;
282 }287 }
283 const elapsed_ns = timer.read();288 const elapsed_ns = benchTime(io) - start;
284289
285 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;290 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
286 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);291 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
...@@ -293,14 +298,14 @@ pub fn benchmarkHashSmallKeysArray(...@@ -293,14 +298,14 @@ pub fn benchmarkHashSmallKeysArray(
293 };298 };
294}299}
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 {
297 var blocks = try allocator.alloc(u8, bytes);302 var blocks = try allocator.alloc(u8, bytes);
298 defer allocator.free(blocks);303 defer allocator.free(blocks);
299 random.bytes(blocks);304 random.bytes(blocks);
300305
301 const key_count = bytes / key_size;306 const key_count = bytes / key_size;
302307
303 var timer = try Timer.start();308 const start = benchTime(io);
304309
305 var sum: u64 = 0;310 var sum: u64 = 0;
306 for (0..key_count) |i| {311 for (0..key_count) |i| {
...@@ -320,7 +325,7 @@ pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize,...@@ -320,7 +325,7 @@ pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize,
320 };325 };
321 sum +%= final;326 sum +%= final;
322 }327 }
323 const elapsed_ns = timer.read();328 const elapsed_ns = benchTime(io) - start;
324329
325 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;330 const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
326 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);331 const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
...@@ -454,7 +459,7 @@ pub fn main(init: std.process.Init) !void {...@@ -454,7 +459,7 @@ pub fn main(init: std.process.Init) !void {
454 // This allows easier comparison between different implementations.459 // This allows easier comparison between different implementations.
455 if (H.has_iterative_api and !test_small_key_only) {460 if (H.has_iterative_api and !test_small_key_only) {
456 prng.seed(seed);461 prng.seed(seed);
457 const result = try benchmarkHash(H, count, allocator);462 const result = try benchmarkHash(H, count, allocator, io);
458 try stdout.print(" iterative: {:5} MiB/s [{x:0<16}]\n", .{ result.throughput / (1 * MiB), result.hash });463 try stdout.print(" iterative: {:5} MiB/s [{x:0<16}]\n", .{ result.throughput / (1 * MiB), result.hash });
459 try stdout.flush();464 try stdout.flush();
460 }465 }
...@@ -462,7 +467,7 @@ pub fn main(init: std.process.Init) !void {...@@ -462,7 +467,7 @@ pub fn main(init: std.process.Init) !void {
462 if (!test_iterative_only) {467 if (!test_iterative_only) {
463 if (key_size) |size| {468 if (key_size) |size| {
464 prng.seed(seed);469 prng.seed(seed);
465 const result_small = try benchmarkHashSmallKeys(H, size, count, allocator);470 const result_small = try benchmarkHashSmallKeys(H, size, count, allocator, io);
466 try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{471 try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{
467 size,472 size,
468 result_small.throughput / (1 * MiB),473 result_small.throughput / (1 * MiB),
...@@ -476,9 +481,9 @@ pub fn main(init: std.process.Init) !void {...@@ -476,9 +481,9 @@ pub fn main(init: std.process.Init) !void {
476 inline for (sizes) |exact_size| {481 inline for (sizes) |exact_size| {
477 if (size == exact_size) {482 if (size == exact_size) {
478 prng.seed(seed);483 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);
480 prng.seed(seed);485 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);
482 try stdout.print(" array: {:5} MiB/s [{x:0<16}]\n", .{487 try stdout.print(" array: {:5} MiB/s [{x:0<16}]\n", .{
483 result_array.throughput / (1 * MiB),488 result_array.throughput / (1 * MiB),
484 result_array.hash,489 result_array.hash,
...@@ -493,7 +498,7 @@ pub fn main(init: std.process.Init) !void {...@@ -493,7 +498,7 @@ pub fn main(init: std.process.Init) !void {
493 }498 }
494 } else {499 } else {
495 prng.seed(seed);500 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);
497 try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{502 try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{
498 default_small_key_size,503 default_small_key_size,
499 result_small.throughput / (1 * MiB),504 result_small.throughput / (1 * MiB),
...@@ -507,7 +512,7 @@ pub fn main(init: std.process.Init) !void {...@@ -507,7 +512,7 @@ pub fn main(init: std.process.Init) !void {
507 try stdout.print(" array:\n", .{});512 try stdout.print(" array:\n", .{});
508 inline for (sizes) |exact_size| {513 inline for (sizes) |exact_size| {
509 prng.seed(seed);514 prng.seed(seed);
510 const result = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator);515 const result = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator, io);
511 try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{516 try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{
512 exact_size,517 exact_size,
513 result.throughput / (1 * MiB),518 result.throughput / (1 * MiB),
...@@ -518,7 +523,7 @@ pub fn main(init: std.process.Init) !void {...@@ -518,7 +523,7 @@ pub fn main(init: std.process.Init) !void {
518 try stdout.print(" array ptr: \n", .{});523 try stdout.print(" array ptr: \n", .{});
519 inline for (sizes) |exact_size| {524 inline for (sizes) |exact_size| {
520 prng.seed(seed);525 prng.seed(seed);
521 const result = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator);526 const result = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator, io);
522 try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{527 try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{
523 exact_size,528 exact_size,
524 result.throughput / (1 * MiB),529 result.throughput / (1 * MiB),
lib/std/unicode/throughput_test.zig+14-12
...@@ -2,7 +2,6 @@ const std = @import("std");...@@ -2,7 +2,6 @@ const std = @import("std");
2const Io = std.Io;2const Io = std.Io;
3const time = std.time;3const time = std.time;
4const unicode = std.unicode;4const unicode = std.unicode;
5const Timer = std.time.Timer;
65
7const N = 1_000_000;6const N = 1_000_000;
87
...@@ -15,12 +14,14 @@ const ResultCount = struct {...@@ -15,12 +14,14 @@ const ResultCount = struct {
15 throughput: u64,14 throughput: u64,
16};15};
1716
18fn benchmarkCodepointCount(buf: []const u8) !ResultCount {17fn benchTime(io: Io) i96 {
19 var timer = try Timer.start();18 return Io.Clock.awake.now(io).nanoseconds;
19}
2020
21fn benchmarkCodepointCount(buf: []const u8, io: Io) !ResultCount {
21 const bytes = N * buf.len;22 const bytes = N * buf.len;
2223
23 const start = timer.lap();24 const start = benchTime(io);
24 var i: usize = 0;25 var i: usize = 0;
25 var r: usize = undefined;26 var r: usize = undefined;
26 while (i < N) : (i += 1) {27 while (i < N) : (i += 1) {
...@@ -30,7 +31,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {...@@ -30,7 +31,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
30 .{buf},31 .{buf},
31 );32 );
32 }33 }
33 const end = timer.read();34 const end = benchTime(io);
3435
35 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;36 const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
36 const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));37 const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));
...@@ -38,44 +39,45 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {...@@ -38,44 +39,45 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
38 return ResultCount{ .count = r, .throughput = throughput };39 return ResultCount{ .count = r, .throughput = throughput };
39}40}
4041
41pub fn main() !void {42pub fn main(init: std.process.Init) !void {
42 // Size of buffer is about size of printed message.43 // Size of buffer is about size of printed message.
44 const io = init.io;
43 var stdout_buffer: [0x100]u8 = undefined;45 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);
45 const stdout = &stdout_writer.interface;47 const stdout = &stdout_writer.interface;
4648
47 try stdout.print("short ASCII strings\n", .{});49 try stdout.print("short ASCII strings\n", .{});
48 try stdout.flush();50 try stdout.flush();
49 {51 {
50 const result = try benchmarkCodepointCount("abc");52 const result = try benchmarkCodepointCount("abc", io);
51 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });53 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
52 }54 }
5355
54 try stdout.print("short Unicode strings\n", .{});56 try stdout.print("short Unicode strings\n", .{});
55 try stdout.flush();57 try stdout.flush();
56 {58 {
57 const result = try benchmarkCodepointCount("ŌŌŌ");59 const result = try benchmarkCodepointCount("ŌŌŌ", io);
58 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });60 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
59 }61 }
6062
61 try stdout.print("pure ASCII strings\n", .{});63 try stdout.print("pure ASCII strings\n", .{});
62 try stdout.flush();64 try stdout.flush();
63 {65 {
64 const result = try benchmarkCodepointCount("hello" ** 16);66 const result = try benchmarkCodepointCount("hello" ** 16, io);
65 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });67 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
66 }68 }
6769
68 try stdout.print("pure Unicode strings\n", .{});70 try stdout.print("pure Unicode strings\n", .{});
69 try stdout.flush();71 try stdout.flush();
70 {72 {
71 const result = try benchmarkCodepointCount("こんにちは" ** 16);73 const result = try benchmarkCodepointCount("こんにちは" ** 16, io);
72 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });74 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
73 }75 }
7476
75 try stdout.print("mixed ASCII/Unicode strings\n", .{});77 try stdout.print("mixed ASCII/Unicode strings\n", .{});
76 try stdout.flush();78 try stdout.flush();
77 {79 {
78 const result = try benchmarkCodepointCount("Hyvää huomenta" ** 16);80 const result = try benchmarkCodepointCount("Hyvää huomenta" ** 16, io);
79 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });81 try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
80 }82 }
81 try stdout.flush();83 try stdout.flush();