用 Zig 实现 yes 命令
起因是看到一篇文章[1],作者介绍了如何用 Rust 优化 yes 命令,第一个 buffer 的版本还比较好懂,第二个复用 buffer 的就没有那么直接了。想了下用 Zig 实现会是怎么样?于是就有了下面的测试:
测试时会用到 pv[2] 命令,需要单独安装
Buffer Write 版本
代码语言:javascript复制const std = @import("std");
pub fn main() !void {
const argv = std.os.argv;
const output: []const u8 = if (argv.len > 1)
argv.ptr[1][0..std.mem.len(argv.ptr[1])]
else
"y";
const out = std.io.getStdOut();
var f = std.io.bufferedWriter(out.writer());
while ((try f.write(output)) > 0) {
_ = try f.write("n");
}
}
编译运行
代码语言:javascript复制zig build-exe yes.zig -Drelease-safe
./yes | pv -r > /dev/null
大概是 116Mib/s
复用 Buffer 版本
代码语言:javascript复制const std = @import("std");
const BUFFER_CAP = 64 * 1024;
fn fill_up_buffer(buf: *[BUFFER_CAP]u8, output: []const u8) []const u8 {
if (output.len > buf.len / 2) {
return output;
}
std.mem.copy(u8, buf, output);
std.mem.copy(u8, buf[output.len..], "n");
var buffer_size = output.len 1;
while (buffer_size < buf.len / 2) {
std.mem.copy(u8, buf[buffer_size..], buf[0..buffer_size]);
buffer_size *= 2;
}
return buf;
}
pub fn main() !void {
const argv = std.os.argv;
const output: []const u8 = if (argv.len > 1)
argv.ptr[1][0..std.mem.len(argv.ptr[1])]
else
"y";
var buffer: [BUFFER_CAP]u8 = undefined;
const body = fill_up_buffer(&buffer, output);
const stdout = std.io.getStdOut();
var writer = stdout.writer();
while ((try writer.write(body)) > 0) {}
}
同样的方式编译执行,速率大概是: 5.4Gib/s
而且,这个版本相比 Rust 的实现,个人感觉,要清晰不少。
引用链接
[1]
一篇文章: https://endler.dev/2017/yes/
[2]
pv: https://linux.die.net/man/1/pv