管道输出到头/尾所需的时间

管道输出到头/尾所需的时间

一个目录下有很多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

相关内容