mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
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>
This commit is contained in:
@@ -5,7 +5,6 @@ const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const time = std.time;
|
||||
const Timer = time.Timer;
|
||||
const Random = std.Random;
|
||||
|
||||
const KiB = 1024;
|
||||
@@ -72,7 +71,11 @@ const Result = struct {
|
||||
const long_block_size: usize = 8 * 8192;
|
||||
const short_block_size: usize = 8;
|
||||
|
||||
pub fn benchmark(comptime H: anytype, bytes: usize, comptime block_size: usize) !Result {
|
||||
pub fn benchTime(io: Io) i96 {
|
||||
return Io.Clock.awake.now(io).nanoseconds;
|
||||
}
|
||||
|
||||
pub fn benchmark(comptime H: anytype, io: Io, bytes: usize, comptime block_size: usize) !Result {
|
||||
var rng = blk: {
|
||||
if (H.init_u8s) |init| {
|
||||
break :blk H.ty.init(init[0..].*);
|
||||
@@ -86,12 +89,11 @@ pub fn benchmark(comptime H: anytype, bytes: usize, comptime block_size: usize)
|
||||
var block: [block_size]u8 = undefined;
|
||||
|
||||
var offset: usize = 0;
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
while (offset < bytes) : (offset += block.len) {
|
||||
rng.fill(block[0..]);
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));
|
||||
@@ -187,7 +189,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
try stdout.print("{s} (long outputs)\n", .{R.name});
|
||||
try stdout.flush();
|
||||
|
||||
const result_long = try benchmark(R, count, long_block_size);
|
||||
const result_long = try benchmark(R, io, count, long_block_size);
|
||||
try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
|
||||
}
|
||||
}
|
||||
@@ -198,7 +200,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
try stdout.print("{s} (short outputs)\n", .{R.name});
|
||||
try stdout.flush();
|
||||
|
||||
const result_short = try benchmark(R, count, short_block_size);
|
||||
const result_short = try benchmark(R, io, count, short_block_size);
|
||||
try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
|
||||
}
|
||||
}
|
||||
@@ -211,7 +213,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
try stdout.print("{s} (cryptographic, long outputs)\n", .{R.name});
|
||||
try stdout.flush();
|
||||
|
||||
const result_long = try benchmark(R, count, long_block_size);
|
||||
const result_long = try benchmark(R, io, count, long_block_size);
|
||||
try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
|
||||
}
|
||||
}
|
||||
@@ -222,7 +224,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
try stdout.print("{s} (cryptographic, short outputs)\n", .{R.name});
|
||||
try stdout.flush();
|
||||
|
||||
const result_short = try benchmark(R, count, short_block_size);
|
||||
const result_short = try benchmark(R, io, count, short_block_size);
|
||||
try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const mem = std.mem;
|
||||
const time = std.time;
|
||||
const Timer = std.time.Timer;
|
||||
const crypto = std.crypto;
|
||||
|
||||
const KiB = 1024;
|
||||
@@ -45,15 +44,18 @@ const parallel_hashes = [_]Crypto{
|
||||
|
||||
const block_size: usize = 8 * 8192;
|
||||
|
||||
pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64 {
|
||||
pub fn benchTime(io: Io) i96 {
|
||||
return Io.Clock.awake.now(io).nanoseconds;
|
||||
}
|
||||
|
||||
pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int, io: Io) !u64 {
|
||||
const blocks_count = bytes / block_size;
|
||||
var block: [block_size]u8 = undefined;
|
||||
random.bytes(&block);
|
||||
|
||||
var h = Hash.init(.{});
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
for (0..blocks_count) |_| {
|
||||
h.update(&block);
|
||||
}
|
||||
@@ -61,7 +63,7 @@ pub fn benchmarkHash(comptime Hash: anytype, comptime bytes: comptime_int) !u64
|
||||
h.final(&final);
|
||||
std.mem.doNotOptimizeAway(final);
|
||||
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
|
||||
@@ -74,13 +76,12 @@ pub fn benchmarkHashParallel(comptime Hash: anytype, comptime bytes: comptime_in
|
||||
defer allocator.free(data);
|
||||
random.bytes(data);
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
var final: [Hash.digest_length]u8 = undefined;
|
||||
try Hash.hashParallel(data, &final, .{}, allocator, io);
|
||||
std.mem.doNotOptimizeAway(final);
|
||||
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
|
||||
@@ -109,7 +110,7 @@ const macs = [_]Crypto{
|
||||
Crypto{ .ty = crypto.auth.cmac.CmacAes128, .name = "aes-cmac" },
|
||||
};
|
||||
|
||||
pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
|
||||
pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int, io: Io) !u64 {
|
||||
var in: [512 * KiB]u8 = undefined;
|
||||
random.bytes(in[0..]);
|
||||
|
||||
@@ -119,13 +120,12 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
|
||||
|
||||
var mac: [Mac.mac_length]u8 = undefined;
|
||||
var offset: usize = 0;
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
while (offset < bytes) : (offset += in.len) {
|
||||
Mac.create(mac[0..], in[0..], key[0..]);
|
||||
mem.doNotOptimizeAway(&mac);
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(bytes / elapsed_s));
|
||||
@@ -135,7 +135,7 @@ pub fn benchmarkMac(comptime Mac: anytype, comptime bytes: comptime_int) !u64 {
|
||||
|
||||
const exchanges = [_]Crypto{Crypto{ .ty = crypto.dh.X25519, .name = "x25519" }};
|
||||
|
||||
pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int) !u64 {
|
||||
pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_count: comptime_int, io: Io) !u64 {
|
||||
std.debug.assert(DhKeyExchange.shared_length >= DhKeyExchange.secret_length);
|
||||
|
||||
var secret: [DhKeyExchange.shared_length]u8 = undefined;
|
||||
@@ -144,8 +144,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
|
||||
var public: [DhKeyExchange.shared_length]u8 = undefined;
|
||||
random.bytes(public[0..]);
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < exchange_count) : (i += 1) {
|
||||
@@ -155,7 +154,7 @@ pub fn benchmarkKeyExchange(comptime DhKeyExchange: anytype, comptime exchange_c
|
||||
mem.doNotOptimizeAway(&out);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(exchange_count / elapsed_s));
|
||||
@@ -177,8 +176,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count
|
||||
const msg = [_]u8{0} ** 64;
|
||||
const key_pair = Signature.KeyPair.generate(io);
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < signatures_count) : (i += 1) {
|
||||
@@ -186,7 +184,7 @@ pub fn benchmarkSignature(comptime Signature: anytype, comptime signatures_count
|
||||
mem.doNotOptimizeAway(&sig);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
|
||||
@@ -206,8 +204,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign
|
||||
const key_pair = Signature.KeyPair.generate(io);
|
||||
const sig = try key_pair.sign(&msg, null);
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < signatures_count) : (i += 1) {
|
||||
@@ -215,7 +212,7 @@ pub fn benchmarkSignatureVerification(comptime Signature: anytype, comptime sign
|
||||
mem.doNotOptimizeAway(&sig);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(signatures_count / elapsed_s));
|
||||
@@ -235,8 +232,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime
|
||||
element.* = Signature.BatchElement{ .sig = sig, .msg = &msg, .public_key = key_pair.public_key };
|
||||
}
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < signatures_count) : (i += 1) {
|
||||
@@ -244,7 +240,7 @@ pub fn benchmarkBatchSignatureVerification(comptime Signature: anytype, comptime
|
||||
mem.doNotOptimizeAway(&sig);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = batch.len * @as(u64, @intFromFloat(signatures_count / elapsed_s));
|
||||
@@ -261,8 +257,7 @@ const kems = [_]Crypto{
|
||||
pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {
|
||||
const key_pair = Kem.KeyPair.generate(io);
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < kems_count) : (i += 1) {
|
||||
@@ -270,7 +265,7 @@ pub fn benchmarkKem(comptime Kem: anytype, comptime kems_count: comptime_int, io
|
||||
mem.doNotOptimizeAway(&e);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
|
||||
@@ -283,8 +278,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
|
||||
|
||||
const e = key_pair.public_key.encaps(io);
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < kems_count) : (i += 1) {
|
||||
@@ -292,7 +286,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
|
||||
mem.doNotOptimizeAway(&ss2);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
|
||||
@@ -301,8 +295,7 @@ pub fn benchmarkKemDecaps(comptime Kem: anytype, comptime kems_count: comptime_i
|
||||
}
|
||||
|
||||
pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_int, io: std.Io) !u64 {
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < kems_count) : (i += 1) {
|
||||
@@ -310,7 +303,7 @@ pub fn benchmarkKemKeyGen(comptime Kem: anytype, comptime kems_count: comptime_i
|
||||
mem.doNotOptimizeAway(&key_pair);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(kems_count / elapsed_s));
|
||||
@@ -337,7 +330,7 @@ const aeads = [_]Crypto{
|
||||
Crypto{ .ty = crypto.aead.isap.IsapA128A, .name = "isapa128a" },
|
||||
};
|
||||
|
||||
pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64 {
|
||||
pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int, io: Io) !u64 {
|
||||
var in: [512 * KiB]u8 = undefined;
|
||||
random.bytes(in[0..]);
|
||||
|
||||
@@ -350,14 +343,13 @@ pub fn benchmarkAead(comptime Aead: anytype, comptime bytes: comptime_int) !u64
|
||||
random.bytes(nonce[0..]);
|
||||
|
||||
var offset: usize = 0;
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
while (offset < bytes) : (offset += in.len) {
|
||||
Aead.encrypt(in[0..], tag[0..], in[0..], &[_]u8{}, nonce, key);
|
||||
try Aead.decrypt(in[0..], in[0..], tag, &[_]u8{}, nonce, key);
|
||||
}
|
||||
mem.doNotOptimizeAway(&in);
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(2 * bytes / elapsed_s));
|
||||
@@ -370,15 +362,14 @@ const aes = [_]Crypto{
|
||||
Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-single" },
|
||||
};
|
||||
|
||||
pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int) !u64 {
|
||||
pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int, io: Io) !u64 {
|
||||
var key: [Aes.key_bits / 8]u8 = undefined;
|
||||
random.bytes(key[0..]);
|
||||
const ctx = Aes.initEnc(key);
|
||||
|
||||
var in = [_]u8{0} ** 16;
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < count) : (i += 1) {
|
||||
@@ -386,7 +377,7 @@ pub fn benchmarkAes(comptime Aes: anytype, comptime count: comptime_int) !u64 {
|
||||
}
|
||||
}
|
||||
mem.doNotOptimizeAway(&in);
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(count / elapsed_s));
|
||||
@@ -399,15 +390,14 @@ const aes8 = [_]Crypto{
|
||||
Crypto{ .ty = crypto.core.aes.Aes256, .name = "aes256-8" },
|
||||
};
|
||||
|
||||
pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int) !u64 {
|
||||
pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int, io: Io) !u64 {
|
||||
var key: [Aes.key_bits / 8]u8 = undefined;
|
||||
random.bytes(key[0..]);
|
||||
const ctx = Aes.initEnc(key);
|
||||
|
||||
var in = [_]u8{0} ** (8 * 16);
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < count) : (i += 1) {
|
||||
@@ -415,7 +405,7 @@ pub fn benchmarkAes8(comptime Aes: anytype, comptime count: comptime_int) !u64 {
|
||||
}
|
||||
}
|
||||
mem.doNotOptimizeAway(&in);
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(8 * count / elapsed_s));
|
||||
@@ -468,8 +458,7 @@ fn benchmarkPwhash(
|
||||
const needs_salt = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type != std.Io;
|
||||
const salt: [16]u8 = .{0} ** 16;
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
{
|
||||
var i: usize = 0;
|
||||
while (i < count) : (i += 1) {
|
||||
@@ -483,7 +472,7 @@ fn benchmarkPwhash(
|
||||
mem.doNotOptimizeAway(&buf);
|
||||
}
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = elapsed_s / count;
|
||||
@@ -554,7 +543,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
|
||||
inline for (hashes) |H| {
|
||||
if (filter == null or std.mem.find(u8, H.name, filter.?) != null) {
|
||||
const throughput = try benchmarkHash(H.ty, mode(128 * MiB));
|
||||
const throughput = try benchmarkHash(H.ty, mode(128 * MiB), io);
|
||||
try stdout.print("{s:>17}: {:10} MiB/s\n", .{ H.name, throughput / (1 * MiB) });
|
||||
try stdout.flush();
|
||||
}
|
||||
@@ -570,7 +559,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
|
||||
inline for (macs) |M| {
|
||||
if (filter == null or std.mem.find(u8, M.name, filter.?) != null) {
|
||||
const throughput = try benchmarkMac(M.ty, mode(128 * MiB));
|
||||
const throughput = try benchmarkMac(M.ty, mode(128 * MiB), io);
|
||||
try stdout.print("{s:>17}: {:10} MiB/s\n", .{ M.name, throughput / (1 * MiB) });
|
||||
try stdout.flush();
|
||||
}
|
||||
@@ -578,7 +567,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
|
||||
inline for (exchanges) |E| {
|
||||
if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
|
||||
const throughput = try benchmarkKeyExchange(E.ty, mode(1000));
|
||||
const throughput = try benchmarkKeyExchange(E.ty, mode(1000), io);
|
||||
try stdout.print("{s:>17}: {:10} exchanges/s\n", .{ E.name, throughput });
|
||||
try stdout.flush();
|
||||
}
|
||||
@@ -610,7 +599,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
|
||||
inline for (aeads) |E| {
|
||||
if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
|
||||
const throughput = try benchmarkAead(E.ty, mode(128 * MiB));
|
||||
const throughput = try benchmarkAead(E.ty, mode(128 * MiB), io);
|
||||
try stdout.print("{s:>17}: {:10} MiB/s\n", .{ E.name, throughput / (1 * MiB) });
|
||||
try stdout.flush();
|
||||
}
|
||||
@@ -618,7 +607,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
|
||||
inline for (aes) |E| {
|
||||
if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
|
||||
const throughput = try benchmarkAes(E.ty, mode(100000000));
|
||||
const throughput = try benchmarkAes(E.ty, mode(100000000), io);
|
||||
try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
|
||||
try stdout.flush();
|
||||
}
|
||||
@@ -626,7 +615,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
|
||||
inline for (aes8) |E| {
|
||||
if (filter == null or std.mem.find(u8, E.name, filter.?) != null) {
|
||||
const throughput = try benchmarkAes8(E.ty, mode(10000000));
|
||||
const throughput = try benchmarkAes8(E.ty, mode(10000000), io);
|
||||
try stdout.print("{s:>17}: {:10} ops/s\n", .{ E.name, throughput });
|
||||
try stdout.flush();
|
||||
}
|
||||
|
||||
+26
-21
@@ -4,7 +4,6 @@ const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const time = std.time;
|
||||
const Timer = time.Timer;
|
||||
const hash = std.hash;
|
||||
|
||||
const KiB = 1024;
|
||||
@@ -111,7 +110,11 @@ const Result = struct {
|
||||
|
||||
const block_size: usize = 8 * 8192;
|
||||
|
||||
pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Allocator) !Result {
|
||||
pub fn benchTime(io: Io) i96 {
|
||||
return Io.Clock.awake.now(io).nanoseconds;
|
||||
}
|
||||
|
||||
pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Allocator, io: Io) !Result {
|
||||
var blocks = try allocator.alloc(u8, bytes);
|
||||
defer allocator.free(blocks);
|
||||
random.bytes(blocks);
|
||||
@@ -131,7 +134,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
|
||||
break :blk .init();
|
||||
};
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = benchTime(io);
|
||||
for (0..block_count) |i| {
|
||||
h.update(blocks[i * block_size ..][0..block_size]);
|
||||
}
|
||||
@@ -143,7 +146,7 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc
|
||||
h.final();
|
||||
std.mem.doNotOptimizeAway(final);
|
||||
|
||||
const elapsed_ns = timer.read();
|
||||
const elapsed_ns = benchTime(io) - start;
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
|
||||
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
|
||||
};
|
||||
}
|
||||
|
||||
pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator) !Result {
|
||||
pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator, io: Io) !Result {
|
||||
var blocks = try allocator.alloc(u8, bytes);
|
||||
defer allocator.free(blocks);
|
||||
random.bytes(blocks);
|
||||
|
||||
const key_count = bytes / key_size;
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = benchTime(io);
|
||||
|
||||
var sum: u64 = 0;
|
||||
for (0..key_count) |i| {
|
||||
@@ -182,7 +185,7 @@ pub fn benchmarkHashSmallKeys(comptime H: anytype, key_size: usize, bytes: usize
|
||||
};
|
||||
sum +%= final;
|
||||
}
|
||||
const elapsed_ns = timer.read();
|
||||
const elapsed_ns = benchTime(io) - start;
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
|
||||
const size_float: f64 = @floatFromInt(key_count * key_size);
|
||||
@@ -204,6 +207,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
|
||||
comptime key_size: usize,
|
||||
bytes: usize,
|
||||
allocator: std.mem.Allocator,
|
||||
io: Io,
|
||||
) !Result {
|
||||
var blocks = try allocator.alloc(u8, bytes);
|
||||
defer allocator.free(blocks);
|
||||
@@ -211,7 +215,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
|
||||
|
||||
const key_count = bytes / key_size;
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = benchTime(io);
|
||||
|
||||
var sum: u64 = 0;
|
||||
for (0..key_count) |i| {
|
||||
@@ -231,7 +235,7 @@ pub fn benchmarkHashSmallKeysArrayPtr(
|
||||
};
|
||||
sum +%= final;
|
||||
}
|
||||
const elapsed_ns = timer.read();
|
||||
const elapsed_ns = benchTime(io) - start;
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
|
||||
const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
|
||||
@@ -252,6 +256,7 @@ pub fn benchmarkHashSmallKeysArray(
|
||||
comptime key_size: usize,
|
||||
bytes: usize,
|
||||
allocator: std.mem.Allocator,
|
||||
io: Io,
|
||||
) !Result {
|
||||
var blocks = try allocator.alloc(u8, bytes);
|
||||
defer allocator.free(blocks);
|
||||
@@ -260,7 +265,7 @@ pub fn benchmarkHashSmallKeysArray(
|
||||
const key_count = bytes / key_size;
|
||||
|
||||
var i: usize = 0;
|
||||
var timer = try Timer.start();
|
||||
const start = benchTime(io);
|
||||
|
||||
var sum: u64 = 0;
|
||||
while (i < key_count) : (i += 1) {
|
||||
@@ -280,7 +285,7 @@ pub fn benchmarkHashSmallKeysArray(
|
||||
};
|
||||
sum +%= final;
|
||||
}
|
||||
const elapsed_ns = timer.read();
|
||||
const elapsed_ns = benchTime(io) - start;
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
|
||||
const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
|
||||
@@ -293,14 +298,14 @@ pub fn benchmarkHashSmallKeysArray(
|
||||
};
|
||||
}
|
||||
|
||||
pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator) !Result {
|
||||
pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize, allocator: std.mem.Allocator, io: Io) !Result {
|
||||
var blocks = try allocator.alloc(u8, bytes);
|
||||
defer allocator.free(blocks);
|
||||
random.bytes(blocks);
|
||||
|
||||
const key_count = bytes / key_size;
|
||||
|
||||
var timer = try Timer.start();
|
||||
const start = benchTime(io);
|
||||
|
||||
var sum: u64 = 0;
|
||||
for (0..key_count) |i| {
|
||||
@@ -320,7 +325,7 @@ pub fn benchmarkHashSmallApi(comptime H: anytype, key_size: usize, bytes: usize,
|
||||
};
|
||||
sum +%= final;
|
||||
}
|
||||
const elapsed_ns = timer.read();
|
||||
const elapsed_ns = benchTime(io) - start;
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(elapsed_ns)) / time.ns_per_s;
|
||||
const throughput: u64 = @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s);
|
||||
@@ -454,7 +459,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
// This allows easier comparison between different implementations.
|
||||
if (H.has_iterative_api and !test_small_key_only) {
|
||||
prng.seed(seed);
|
||||
const result = try benchmarkHash(H, count, allocator);
|
||||
const result = try benchmarkHash(H, count, allocator, io);
|
||||
try stdout.print(" iterative: {:5} MiB/s [{x:0<16}]\n", .{ result.throughput / (1 * MiB), result.hash });
|
||||
try stdout.flush();
|
||||
}
|
||||
@@ -462,7 +467,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
if (!test_iterative_only) {
|
||||
if (key_size) |size| {
|
||||
prng.seed(seed);
|
||||
const result_small = try benchmarkHashSmallKeys(H, size, count, allocator);
|
||||
const result_small = try benchmarkHashSmallKeys(H, size, count, allocator, io);
|
||||
try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{
|
||||
size,
|
||||
result_small.throughput / (1 * MiB),
|
||||
@@ -476,9 +481,9 @@ pub fn main(init: std.process.Init) !void {
|
||||
inline for (sizes) |exact_size| {
|
||||
if (size == exact_size) {
|
||||
prng.seed(seed);
|
||||
const result_array = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator);
|
||||
const result_array = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator, io);
|
||||
prng.seed(seed);
|
||||
const result_ptr = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator);
|
||||
const result_ptr = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator, io);
|
||||
try stdout.print(" array: {:5} MiB/s [{x:0<16}]\n", .{
|
||||
result_array.throughput / (1 * MiB),
|
||||
result_array.hash,
|
||||
@@ -493,7 +498,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
}
|
||||
} else {
|
||||
prng.seed(seed);
|
||||
const result_small = try benchmarkHashSmallKeys(H, default_small_key_size, count, allocator);
|
||||
const result_small = try benchmarkHashSmallKeys(H, default_small_key_size, count, allocator, io);
|
||||
try stdout.print(" small keys: {:3}B {:5} MiB/s {} Hashes/s [{x:0<16}]\n", .{
|
||||
default_small_key_size,
|
||||
result_small.throughput / (1 * MiB),
|
||||
@@ -507,7 +512,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
try stdout.print(" array:\n", .{});
|
||||
inline for (sizes) |exact_size| {
|
||||
prng.seed(seed);
|
||||
const result = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator);
|
||||
const result = try benchmarkHashSmallKeysArray(H, exact_size, count, allocator, io);
|
||||
try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{
|
||||
exact_size,
|
||||
result.throughput / (1 * MiB),
|
||||
@@ -518,7 +523,7 @@ pub fn main(init: std.process.Init) !void {
|
||||
try stdout.print(" array ptr: \n", .{});
|
||||
inline for (sizes) |exact_size| {
|
||||
prng.seed(seed);
|
||||
const result = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator);
|
||||
const result = try benchmarkHashSmallKeysArrayPtr(H, exact_size, count, allocator, io);
|
||||
try stdout.print(" {d: >3}B {:5} MiB/s [{x:0<16}]\n", .{
|
||||
exact_size,
|
||||
result.throughput / (1 * MiB),
|
||||
|
||||
@@ -2,7 +2,6 @@ const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const time = std.time;
|
||||
const unicode = std.unicode;
|
||||
const Timer = std.time.Timer;
|
||||
|
||||
const N = 1_000_000;
|
||||
|
||||
@@ -15,12 +14,14 @@ const ResultCount = struct {
|
||||
throughput: u64,
|
||||
};
|
||||
|
||||
fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
|
||||
var timer = try Timer.start();
|
||||
fn benchTime(io: Io) i96 {
|
||||
return Io.Clock.awake.now(io).nanoseconds;
|
||||
}
|
||||
|
||||
fn benchmarkCodepointCount(buf: []const u8, io: Io) !ResultCount {
|
||||
const bytes = N * buf.len;
|
||||
|
||||
const start = timer.lap();
|
||||
const start = benchTime(io);
|
||||
var i: usize = 0;
|
||||
var r: usize = undefined;
|
||||
while (i < N) : (i += 1) {
|
||||
@@ -30,7 +31,7 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
|
||||
.{buf},
|
||||
);
|
||||
}
|
||||
const end = timer.read();
|
||||
const end = benchTime(io);
|
||||
|
||||
const elapsed_s = @as(f64, @floatFromInt(end - start)) / time.ns_per_s;
|
||||
const throughput = @as(u64, @intFromFloat(@as(f64, @floatFromInt(bytes)) / elapsed_s));
|
||||
@@ -38,44 +39,45 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
|
||||
return ResultCount{ .count = r, .throughput = throughput };
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
pub fn main(init: std.process.Init) !void {
|
||||
// Size of buffer is about size of printed message.
|
||||
const io = init.io;
|
||||
var stdout_buffer: [0x100]u8 = undefined;
|
||||
var stdout_writer = Io.File.stdout().writer(&stdout_buffer);
|
||||
var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer);
|
||||
const stdout = &stdout_writer.interface;
|
||||
|
||||
try stdout.print("short ASCII strings\n", .{});
|
||||
try stdout.flush();
|
||||
{
|
||||
const result = try benchmarkCodepointCount("abc");
|
||||
const result = try benchmarkCodepointCount("abc", io);
|
||||
try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
|
||||
}
|
||||
|
||||
try stdout.print("short Unicode strings\n", .{});
|
||||
try stdout.flush();
|
||||
{
|
||||
const result = try benchmarkCodepointCount("ŌŌŌ");
|
||||
const result = try benchmarkCodepointCount("ŌŌŌ", io);
|
||||
try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
|
||||
}
|
||||
|
||||
try stdout.print("pure ASCII strings\n", .{});
|
||||
try stdout.flush();
|
||||
{
|
||||
const result = try benchmarkCodepointCount("hello" ** 16);
|
||||
const result = try benchmarkCodepointCount("hello" ** 16, io);
|
||||
try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
|
||||
}
|
||||
|
||||
try stdout.print("pure Unicode strings\n", .{});
|
||||
try stdout.flush();
|
||||
{
|
||||
const result = try benchmarkCodepointCount("こんにちは" ** 16);
|
||||
const result = try benchmarkCodepointCount("こんにちは" ** 16, io);
|
||||
try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
|
||||
}
|
||||
|
||||
try stdout.print("mixed ASCII/Unicode strings\n", .{});
|
||||
try stdout.flush();
|
||||
{
|
||||
const result = try benchmarkCodepointCount("Hyvää huomenta" ** 16);
|
||||
const result = try benchmarkCodepointCount("Hyvää huomenta" ** 16, io);
|
||||
try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
|
||||
}
|
||||
try stdout.flush();
|
||||
|
||||
Reference in New Issue
Block a user