管道輸出到頭/尾所需的時間

管道輸出到頭/尾所需的時間

一個目錄下有很多txt檔。

如果我time wc -l *.txt | head這樣做需要

real    0m0.032s
user    0m0.020s
sys     0m0.008s

如果我time wc -l *.txt | tail這樣做需要

real    0m0.156s
user    0m0.076s
sys     0m0.088s

這是否意味著wc會事先知道它正在通過管道傳輸到頭部並且僅計算前 10 個文件並節省時間?換句話說,它知道管道嗎?這是有什麼特別之處嗎wc

答案1

strace對這兩個指令都做了 a 。有趣的是,當你通過管道輸出時,head只有 123 個系統調用。另一方面,當透過管道傳輸到 tail 時,有 245 個系統呼叫(當有更多 *.txt 檔案時,會有更多)。

案例:頭部

以下是透過管道傳輸到 時的最後幾行head

open("file12.txt", O_RDONLY)            = 3
fadvise64(3, 0, 0, POSIX_FADV_SEQUENTIAL) = 0
read(3, "", 16384)                      = 0
write(1, "0 file12.txt\n", 13)          = -1 EPIPE (Broken pipe)
--- SIGPIPE (Broken pipe) @ 0 (0) ---
+++ killed by SIGPIPE +++

wc嘗試寫入第 12 個檔案的輸出時,會出現錯誤EPIPE。這就是為什麼head在得到第11行後退出的原因。退出時headwc得到SIGPIPE.如上面的 strace 輸出所示,wc首先嘗試寫入該管道(head不再從中讀取)並收到管道已損壞的錯誤。

當進程嘗試寫入另一端未連接進程的管道時,會向進程發送 SIGPIPE 訊號。 - 從維基百科

案例:尾部

當透過管道傳輸到 時tail,沒有與上方類似的情況。將所有輸出寫入tail需要一直連接的管道後,wc 優雅地結束。tail需要所有行才能列印最後 10 行。當沒有更多輸出可供讀取時,tail也列印行並優雅退出

答案2

如果任何不阻塞的進程SIGPIPE的輸出到達無人讀取的管道的寫入端,則該進程將被終止。

因此,一旦head關閉其輸入(即終止),wc就會死亡,這比完成所有工作花費的時間更少。

答案3

你可以這樣做來消失你的文件:

time wc -l *.txt > tee   | tail 

但是您為 tee 命令添加了一點時間time

tee command

root@debian:/home/mohsen/test# time wc -l *.txt > tee   | tail 

real    0m0.005s
user    0m0.000s
sys 0m0.000s

沒有tee command

root@debian:/home/mohsen/test# time wc -l *.txt | tail 
   8 f3.txt
   7 fi.txt
   5 mydata.txt
   4 newfile.txt
   4 t1.txt
   4 t2.txt
   5 test.txt
   4 text.txt
   0 t.txt
  49 total

real    0m0.004s
user    0m0.000s
sys 0m0.000s

相關內容