用 Zig 优化 yes 命令 #4
jiacai2050
started this conversation in
观点交流
Replies: 1 comment 1 reply
-
第二个版本有几个 corner case,重新写了个 //! `yes` unix command in Zig, optimized for speed
//! Reference to: https://github.com/cgati/yes
const std = @import("std");
const BUFFER_CAP = 64 * 1024;
fn fill_up_buffer(buf: *[BUFFER_CAP]u8, word: []const u8) []const u8 {
if (word.len > buf.len / 2) {
return word;
}
std.mem.copy(u8, buf, word);
var buffer_size = word.len;
while (buffer_size < buf.len / 2) {
std.mem.copy(u8, buf[buffer_size..], buf[0..buffer_size]);
buffer_size *= 2;
}
return buf[0..buffer_size];
}
/// Reference to: https://doc.rust-lang.org/std/borrow/enum.Cow.html
const Cow = union(enum) {
owned: std.ArrayList(u8),
ref: []const u8,
fn as_slice(self: Cow) []const u8 {
return switch (self) {
.owned => |o| o.items,
.ref => |r| r,
};
}
fn deinit(self: Cow) void {
return switch (self) {
.owned => |o| o.deinit(),
.ref => {},
};
}
};
pub fn main() !void {
const argv = std.os.argv;
const word = if (argv.len > 1) x: {
var list = std.ArrayList(u8).init(std.heap.page_allocator);
try list.appendSlice(argv.ptr[1][0..std.mem.len(argv.ptr[1])]);
try list.append('\n');
break :x Cow{ .owned = list };
} else Cow{ .ref = "y\n" };
defer word.deinit();
var buffer: [BUFFER_CAP]u8 = undefined;
const body = fill_up_buffer(&buffer, word.as_slice());
const stdout = std.io.getStdOut();
var writer = stdout.writer();
while (true) {
try writer.writeAll(body);
}
} |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
起因是看到一篇文章,作者介绍了如何用 Rust 优化 yes 命令,第一个 buffer 的版本还比较好懂,第二个复用 buffer 的就没有那么直接了。想了下用 Zig 实现会是怎么样?于是就有了下面的测试:
PS:测试时会用的 pv 这个命令
Buffer Write 版本
编译运行
大概是
116Mib/s
复用 Buffer 版本
同样地方式编译执行,速率大概是:
5.4Gib/s
而且,这个版本相比 Rust 的实现,个人感觉,要清晰不少。
Beta Was this translation helpful? Give feedback.
All reactions