Yes, you can
Yes
是一個 GNU core utils 內的一個小工具,他可以幫你快速印出 y
或者其他指定字串。
很顯然的、這是一個簡單的程式,但實際上他的
實作邏輯
比想像中的還要再複雜一點。
trivial solution
以 Rust 當作程式語言的範例、最簡單的實作方式如下:
fn main() {
loop {
println!("y");
}
}
advanced solution
但是、如果你想要實作一個更加完整的版本、那麼你需要考慮到一些問題: 單一次只寫一個字串對於 I/O 來說效率太差。因此可以思考一次寫入一個 buffer 大小的字串。
fn main() {
let buf = "y\n".repeat(4096);
loop {
println!("{}", buf);
}
}
在這種情況下就可以減少 context switch 的次數並提升效率。
splice solution
參考了一下 uutils/coreutils 的實作方式、他是使用 splice 來做的。這個指令是一個 Linux 特有的 系統呼叫 , 跟 sendfile 類似,他可以將兩個 pipe 間的 file descriptor 做 kernel-space 內的資料傳遞、而不用再經過 user-space。 在這種情況下、除了可以減少 I/O 間的 context switch 之外、還可以減少 user-space 與 kernel-space 間的 context switch。
Benchmark
為了可以評斷上面幾種方式的效能、在 Terminal 環境下使用 Pipe 加上 head 指令來做效能測試:
time your_program | head -n 1000000
。
method | time |
---|---|
trivial | 0m1.056s |
buffer (4096) | 0m0.842s |