Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/compiler/reduce.zig
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub fn main() !void {
const arg = args[i];
if (mem.startsWith(u8, arg, "-")) {
if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
const stdout = std.fs.File.stdout().deprecatedWriter();
const stdout = std.fs.File.stdout();
try stdout.writeAll(usage);
return std.process.cleanExit();
} else if (mem.eql(u8, arg, "--")) {
Expand Down
14 changes: 13 additions & 1 deletion lib/std/Random/benchmark.zig
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ fn mode(comptime x: comptime_int) comptime_int {
}

pub fn main() !void {
const stdout = std.fs.File.stdout().deprecatedWriter();
var stdout_buffer: [0x100]u8 = undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're going to flush at every write, instead simply give it an empty buffer. Or, put only one flush at the very end.

Note: this conflicts with another merged patch so you can probably just drop this change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did what you suggested at first but when I checked and print() actually will make multiple syscalls if provided with empty buffer.
Additionally im flushing not after all writes but only before blocking writes e.g. printing results of benchmark and printing header for next benchmark in one syscall since they become available for printing at the same time and it preserves old behavior.

But I guess it doesn't matter for this scripts much so might as well drop it to make implementation simpler.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, it doesn't matter too much, other than that any code that exists, serves as an example for people reading the code to follow, so there's value to always doing best practices, particularly in ziglang/zig. Not a merge blocker though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im not sure which practice of these two you mean to be best? Doing simpler code (no buffering) or doing faster code (with buffering)?

var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;

var buffer: [1024]u8 = undefined;
var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
Expand All @@ -139,6 +141,7 @@ pub fn main() !void {
while (i < args.len) : (i += 1) {
if (std.mem.eql(u8, args[i], "--mode")) {
try stdout.print("{}\n", .{builtin.mode});
try stdout.flush();
return;
} else if (std.mem.eql(u8, args[i], "--filter")) {
i += 1;
Expand Down Expand Up @@ -179,6 +182,8 @@ pub fn main() !void {
inline for (prngs) |R| {
if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) {
try stdout.print("{s} (long outputs)\n", .{R.name});
try stdout.flush();

const result_long = try benchmark(R, count, long_block_size);
try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
}
Expand All @@ -188,6 +193,8 @@ pub fn main() !void {
inline for (prngs) |R| {
if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) {
try stdout.print("{s} (short outputs)\n", .{R.name});
try stdout.flush();

const result_short = try benchmark(R, count, short_block_size);
try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
}
Expand All @@ -199,6 +206,8 @@ pub fn main() !void {
inline for (csprngs) |R| {
if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) {
try stdout.print("{s} (cryptographic, long outputs)\n", .{R.name});
try stdout.flush();

const result_long = try benchmark(R, count, long_block_size);
try stdout.print(" {:5} MiB/s\n", .{result_long.throughput / (1 * MiB)});
}
Expand All @@ -208,10 +217,13 @@ pub fn main() !void {
inline for (csprngs) |R| {
if (filter == null or std.mem.indexOf(u8, R.name, filter.?) != null) {
try stdout.print("{s} (cryptographic, short outputs)\n", .{R.name});
try stdout.flush();

const result_short = try benchmark(R, count, short_block_size);
try stdout.print(" {:5} MiB/s\n", .{result_short.throughput / (1 * MiB)});
}
}
}
}
try stdout.flush();
}
3 changes: 2 additions & 1 deletion lib/std/crypto/benchmark.zig
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,8 @@ fn mode(comptime x: comptime_int) comptime_int {
}

pub fn main() !void {
var stdout_buffer: [4096]u8 = undefined;
// Size of buffer is about size of printed message.
var stdout_buffer: [0x100]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;

Expand Down
37 changes: 31 additions & 6 deletions lib/std/hash/benchmark.zig
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ const Hash = struct {
has_iterative_api: bool = true,
has_crypto_api: bool = false,
has_anytype_api: ?[]const comptime_int = null,
/// `final` value should be read from this field.
has_struct_api: ?[]const u8 = null,
init_u8s: ?[]const u8 = null,
init_u64: ?u64 = null,
init_default: bool = false,
};

const hashes = [_]Hash{
Expand Down Expand Up @@ -54,6 +57,8 @@ const hashes = [_]Hash{
Hash{
.ty = hash.Adler32,
.name = "adler32",
.has_struct_api = "adler",
.init_default = true,
},
Hash{
.ty = hash.crc.Crc32,
Expand Down Expand Up @@ -112,21 +117,29 @@ pub fn benchmarkHash(comptime H: anytype, bytes: usize, allocator: std.mem.Alloc

const block_count = bytes / block_size;

var h = blk: {
var h: H.ty = blk: {
if (H.init_u8s) |init| {
break :blk H.ty.init(init[0..H.ty.key_length]);
break :blk .init(init[0..H.ty.key_length]);
}
if (H.init_u64) |init| {
break :blk H.ty.init(init);
break :blk .init(init);
}
break :blk H.ty.init();
if (H.init_default) {
break :blk .{};
}
break :blk .init();
};

var timer = try Timer.start();
for (0..block_count) |i| {
h.update(blocks[i * block_size ..][0..block_size]);
}
const final = if (H.has_crypto_api) @as(u64, @truncate(h.finalInt())) else h.final();
const final = if (H.has_struct_api) |field_name|
@field(h, field_name)
else if (H.has_crypto_api)
@as(u64, @truncate(h.finalInt()))
else
h.final();
std.mem.doNotOptimizeAway(final);

const elapsed_ns = timer.read();
Expand Down Expand Up @@ -340,7 +353,9 @@ fn mode(comptime x: comptime_int) comptime_int {
}

pub fn main() !void {
const stdout = std.fs.File.stdout().deprecatedWriter();
var stdout_buffer: [0x100]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;

var buffer: [1024]u8 = undefined;
var fixed = std.heap.FixedBufferAllocator.init(buffer[0..]);
Expand All @@ -360,6 +375,7 @@ pub fn main() !void {
while (i < args.len) : (i += 1) {
if (std.mem.eql(u8, args[i], "--mode")) {
try stdout.print("{}\n", .{builtin.mode});
try stdout.flush();
return;
} else if (std.mem.eql(u8, args[i], "--seed")) {
i += 1;
Expand Down Expand Up @@ -397,6 +413,7 @@ pub fn main() !void {
key_size = try std.fmt.parseUnsigned(usize, args[i], 10);
if (key_size.? > block_size) {
try stdout.print("key_size cannot exceed block size of {}\n", .{block_size});
try stdout.flush();
std.process.exit(1);
}
} else if (std.mem.eql(u8, args[i], "--iterative-only")) {
Expand All @@ -416,6 +433,7 @@ pub fn main() !void {

if (test_iterative_only and test_small_key_only) {
try stdout.print("Cannot use iterative-only and small-key-only together!\n", .{});
try stdout.flush();
usage();
std.process.exit(1);
}
Expand All @@ -428,13 +446,15 @@ pub fn main() !void {
if (filter == null or std.mem.indexOf(u8, H.name, filter.?) != null) hash: {
if (!test_iterative_only or H.has_iterative_api) {
try stdout.print("{s}\n", .{H.name});
try stdout.flush();

// Always reseed prior to every call so we are hashing the same buffer contents.
// 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);
try stdout.print(" iterative: {:5} MiB/s [{x:0<16}]\n", .{ result.throughput / (1 * MiB), result.hash });
try stdout.flush();
}

if (!test_iterative_only) {
Expand All @@ -447,6 +467,7 @@ pub fn main() !void {
result_small.throughput / size,
result_small.hash,
});
try stdout.flush();

if (!test_arrays) break :hash;
if (H.has_anytype_api) |sizes| {
Expand All @@ -464,6 +485,7 @@ pub fn main() !void {
result_ptr.throughput / (1 * MiB),
result_ptr.hash,
});
try stdout.flush();
}
}
}
Expand All @@ -476,6 +498,7 @@ pub fn main() !void {
result_small.throughput / default_small_key_size,
result_small.hash,
});
try stdout.flush();

if (!test_arrays) break :hash;
if (H.has_anytype_api) |sizes| {
Expand All @@ -488,6 +511,7 @@ pub fn main() !void {
result.throughput / (1 * MiB),
result.hash,
});
try stdout.flush();
}
try stdout.print(" array ptr: \n", .{});
inline for (sizes) |exact_size| {
Expand All @@ -498,6 +522,7 @@ pub fn main() !void {
result.throughput / (1 * MiB),
result.hash,
});
try stdout.flush();
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/std/log.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@
//! // Print the message to stderr, silently ignoring any errors
//! std.debug.lockStdErr();
//! defer std.debug.unlockStdErr();
//! const stderr = std.fs.File.stderr().deprecatedWriter();
//! nosuspend stderr.print(prefix ++ format ++ "\n", args) catch return;
//! var stderr = std.fs.File.stderr().writer(&.{});
//! nosuspend stderr.interface.print(prefix ++ format ++ "\n", args) catch return;
//! }
//!
//! pub fn main() void {
Expand Down
11 changes: 10 additions & 1 deletion lib/std/unicode/throughput_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -39,35 +39,44 @@ fn benchmarkCodepointCount(buf: []const u8) !ResultCount {
}

pub fn main() !void {
const stdout = std.fs.File.stdout().deprecatedWriter();
// Size of buffer is about size of printed message.
var stdout_buffer: [0x100]u8 = undefined;
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
const stdout = &stdout_writer.interface;

try stdout.print("short ASCII strings\n", .{});
try stdout.flush();
{
const result = try benchmarkCodepointCount("abc");
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("ŌŌŌ");
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);
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);
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);
try stdout.print(" count: {:5} MiB/s [{d}]\n", .{ result.throughput / (1 * MiB), result.count });
}
try stdout.flush();
}