stdbuf用法:增加缓冲区大小

时间:2011-10-17 14:52:32

标签: unix pipe

我有一个awk脚本向stdout发送长字符串(> 10K字符)。

我想增加缓冲区大小,以便一次写入那些长字符串的较大块。我已经将两个管道的时间设置为不同的-o尺寸,但是没有显着的变化

time stdbuf -o 100MB awk -f processing.awk infile.txt | sort -k1,1 > outfile.txt
time stdbuf -o 100MB awk -f processing.awk infile.txt > outfile.txt

real / user / sys时序与另一个非常相似(每个指标+ - 10%)。

我的问题是我是否正确使用stdbuf?谢谢。

FZ。

3 个答案:

答案 0 :(得分:1)

stdbuf所做的是改变C stdlib中的缓冲,即stdinstdoutstderr FILE*的缓冲区。

它不会更改内核中管道缓冲区的大小。这可能是您没有看到任何变化的原因。

众所周知的问题是管道缓冲区大小无法更改且非常小。处理大型文件时,通常最好将中间结果写入文件,而不是将它们传输到另一个应用程序中。因为管道缓冲区非常小,所以在通过管道进行通信的应用程序之间会有很多上下文切换,其开销可能会使应用程序运行时相形见绌。

答案 1 :(得分:0)

stdbuf命令设法改变执行命令的标准I / O通道的缓冲。但是,它(我认为它不能)改变O / S中管道的容量。所以,我不希望看到性能有任何差异。

请注意,不同之处在于,对于大缓冲区,awk将最终在一个怪异的write()系统调用中发送所有数据(除非infile.txt,由脚本修改,它本身大于100 MiB),而通常它会在填充0.5到8 KiB之间的某个缓冲区时写入。然而,如此巨大的write()的好处是微乎其微的;它仍然必须被O / S分割以适应管道(除非O / S做不同的事情 - 经典,我所描述的将是真的。)

答案 2 :(得分:0)

缓冲在管道中的另一种方法是使用dd命令。我发现在某些情况下stdbuf不起作用(例如:在OSX上为git),在继续进行下一步之前,先排空输出是很有用的。这是一个示例,该示例将在向sort发送任何内容之前先消耗1 MB的空间,同时还要写入1MB的块:

awk -f processing.awk infile.txt |
  dd bs=1000000 | # drain/write 1 MB chunks
  sort -k1,1 > outfile.txt

另一个有趣的用例:

git ls-remote origin |
  # obviously psuedo-awk, might print out :refs/tags/{old_versions}
  awk '/filter for interesting stuff/ {massage output}' |
  dd bs=1000000 2> /dev/null | # drain 1 MB and suppress block summary
  xargs -n 10 git push origin