和風網標誌

您對 Bash 管道的思考模型是錯誤的嗎?

日期:

[邁克爾·林奇]遇到了一個奇怪的情況。 為什麼編譯然後運行他的程式將近 10 倍 提速 而不是僅僅運行程式本身? [Michael] 在對程式設計專案進行基準測試時遇到了這個問題,將其簡化為可重複性和分析的基本要素,並發現它突出顯示了 bash 管道如何運作的錯誤思維模型。

情況是這樣的。 [Michael] 的精簡程式所做的第一件事就是啟動計時器。然後它只是讀取併計算一些字節 stdin,然後列印發生這種情況需要多長時間。以以下方式執行測試程式時,大約需要13微秒。

$ echo '00010203040506070809' | xxd -r -p | zig build run -Doptimize=ReleaseFast
bytes: 10
execution time: 13.549µs

當直接執行(已編譯的)程式時,執行時間會增加到 162 微秒。

$ echo '00010203040506070809' | xxd -r -p | ./zig-out/bin/count-bytes
bytes: 10
execution time: 162.195µs

再說一遍,兩者之間的唯一區別 zig build run./zig-out/bin/count-bytes 是首先編譯程式碼,然後立即運行它。第二個只是執行編譯後的程式。

如何新增額外的編譯步驟 減少 執行時間?事實證明,[Michael] 關於 bash 管道如何運作的心智模型是不正確的,而且他在這方面做得很好 解釋它們實際上是如何運作的,以及為什麼會導致奇怪的行為 他在看。

簡而言之,bash 管道中的命令不是按順序啟動的。它們都是同時啟動並並行執行的。這意味著當直接運行時,[Michael] 的位元組計數器程式立即啟動。然後它等待了大約 150 微秒,什麼都不做,而 echo '00010203040506070809' | xxd -r -p 管道的一部分開始傳遞資料供程式讀取。這就是執行已編譯版本時額外執行時間的來源。

那為什麼先編譯它再跑得更快呢?基本原因相同:當 zig build run 命令啟動,它首先花費一點時間編譯程式。然後,當編譯後的程式實際啟動(並開始執行計時器)時,來自 bash 管道的輸入資料已經準備好。因此,新編譯的程式執行時間更短,因為它不會等待管道中早期的資料變得可用。

這是對 bash 管道在幕後如何實際運作的有趣觀察,我們對 [Micheal] 在整個過程和解釋中提供的細節感到高興。遲早,像這樣的細節會突然出現並引起一些人的眉毛,就像發現的用戶一樣 ssh 指令中有關空格的麻煩邊緣情況.

現貨圖片

最新情報

現貨圖片