Beating gnu yes in throughput
2021-04-20
How much work is it to get high throughput?
I just stumbled upon this article:
And it tells me that doing less syscalls improves throughput and the naive implementation is just not good.
As I was wondering how well Zig compares to the GNU yes, I just hacked something together:
const std = @import("std"); pub fn main() anyerror!void { const pattern = "y\n" ** 8192; var out = std.io.getStdOut(); while (true) { out.writeAll(pattern) catch |err| switch (err) { error.NoSpaceLeft => break, else => |e| return e, }; } }
Building that with ReleaseFast gave me this small (and pretty senseless) benchmark:
[felix@denkplatte-v2 quickyes]$ ./zig-yes | pv > /dev/null 24,6GiB 0:00:10 [2,41GiB/s] [felix@denkplatte-v2 quickyes]$ yes | pv > /dev/null 22,7GiB 0:00:10 [2,26GiB/s]
When increasing the buffer size, the transfer speed goes up as well, but there's a sweet-spot for normal write() syscalls. Using writev, aio or io_uring should yield even better transfer rates.
So the sentence
We didn't beat GNU's yes, and there probably is no way.
can be proven wrong by telling them: Use a pretty naive zig implementation!
But to be fair: These aren't relevant numbers, nobody needs to type `y` that quickly, so don't take this blog post too serious, yeah?
Over and out.