Stdbuf用法:增加缓冲区大小



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

我想增加缓冲区大小,以便一次写入更大的长字符串块。我在下面用不同的- 0大小计时两个管道,但没有明显的变化

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%)。

我的问题是我是否使用stdbut正确的方式?谢谢你。

FZ .

stdbuf所做的是改变C标准库中的缓冲区,即stdin, stdoutstderr FILE*的缓冲区。

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

众所周知,管道缓冲区的大小是不可改变的,并且非常小。在处理大文件时,通常最好将中间结果写入文件,而不是将它们管道到另一个应用程序中。由于管道缓冲区非常小,因此将在通过管道通信的应用程序之间进行大量上下文切换,其开销可能会使应用程序运行时相形见绌。

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

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

在管道中进行缓冲的另一种方法是使用dd命令。我发现了一些stdbuf不工作的情况(例如:OSX上的git),在进行管道的下一步之前将输出排干是有用的。下面是一个示例,在向sort发送任何内容之前将消耗1MB,同时还写入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

最新更新