Beating gnu yes in throughput

2021-04-20

How much work is it to get high throughput?

zig (14) response (1)

I just stumbled upon this article:

 

How is GNU `yes` so fast?

 

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.