I’m running into strange behavior with zig build run
, and I’m hoping others might help explain what’s happening.
I have a simple Zig app that I can run with zig build run
. But if I run the compiled binary afterwards, the performance is 10x worse than with zig build run
.
src/main.zig
const std = @import("std");
pub fn countBytes(reader: anytype) !u32 {
var count: u32 = 0;
while (true) {
_ = reader.readByte() catch |err| switch (err) {
error.EndOfStream => {
return count;
},
else => {
return err;
},
};
count += 1;
}
}
pub fn main() !void {
var reader = std.io.getStdIn().reader();
var timer = try std.time.Timer.start();
const start = timer.lap();
const count = try countBytes(&reader);
const end = timer.read();
const elapsed_micros = @as(f64, @floatFromInt(end - start)) / std.time.ns_per_us;
const output = std.io.getStdOut().writer();
try output.print("bytes: {}\n", .{count});
try output.print("execution time: {d:.3}µs\n", .{elapsed_micros});
}
build.zig
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "count-bytes",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
}
$ zig version
0.11.0
Measuring runtime
If I run with zig build run
, I see performance of 13µs:
$ echo '00010203040506070809' | xxd -r -p | zig build run -Doptimize=ReleaseFast
bytes: 10
execution time: 13.549µs
That zig build run
command compiles a binary, but if I run that binary, performance is over 10x worse:
$ echo '00010203040506070809' | xxd -r -p | ./zig-out/bin/count-bytes
bytes: 10
execution time: 162.195µs
I see the same thing if I compile the binary explicitly and run it:
$ rm -rf zig-out && zig build -Doptimize=ReleaseFast && echo '00010203040506070809' | xxd -r -p | ./zig-out/bin/count-bytes
bytes: 10
execution time: 191.093µs
Does anyone know why zig build run
seems to be outperforming the compiled binary by such a large margin?