如何确定shell管道中最慢的组件?

Del*_*ted 3 linux bash grep cut cat

我有一个非常漫长而复杂的shell管道,可以获取2.2Gb的数据并进行处理.目前需要45分钟才能完成.管道是捆绑在一起的一些cut,grep,sort,uniq,grep和awk命令.我怀疑是grep部分导致它花了这么多时间,但我无法确认它.

无论如何,从端到端"分析"整个管道以确定哪个组件最慢,如果它是CPU或IO绑定,那么它可以被优化?

我不能在这里发布整个命令,因为它需要发布专有信息,但我怀疑它是以下位用htop检查它:

grep -v ^[0-9]
Run Code Online (Sandbox Code Playgroud)

pax*_*blo 5

实现此目的的一种方法是逐步建立管道,为每次添加计时,并尽可能多地采用等式(例如输出到终端或文件).一个非常简单的例子如下所示:

pax:~$ time ( cat bigfile >/dev/null )
real 0m4.364s
user 0m0.004s
sys  0m0.300s

pax:~$ time ( cat bigfile | tr 'a' 'b' >/dev/null )
real 0m0.446s
user 0m0.312s
sys  0m0.428s

pax:~$ time ( cat bigfile | tr 'a' 'b' | tail -1000l >/dev/null )
real 0m0.796s
user 0m0.516s
sys  0m0.688s

pax:~$ time ( cat bigfile | tr 'a' 'b' | tail -1000l | sort -u >/dev/null )
real 0m0.892s
user 0m0.556s
sys  0m0.756s
Run Code Online (Sandbox Code Playgroud)

如果您将上述用户和系统时间相加,您会看到增量增加为:

  • 0.304(0.004 + 0.300)秒为cat;
  • 0.436(0.312 + 0.428 - 0.304)秒为tr;
  • 0.464(0.516 + 0.688 - 0.436 - 0.304)秒为tail; 和
  • 0.108(0.556 + 0.756 - 0.464 - 0.436 - 0.304)秒为sort.

这告诉我要研究的主要内容是tailtr.

现在很明显,这只适用于CPU,我可能应该在每个阶段进行多次运行以达到平均目的,但这是我将采取的基本第一种方法.

如果事实证明它确实是你的grep,那么还有其他一些选择.还有许多其他命令可以删除不以数字开头的行,但是您可能会发现用于执行此操作的自定义命令可能更快,伪代码(未经测试,但您应该明白):

state = echo
lastchar = newline
while not end of file:
    read big chunk from file
    for every char in chunk:
        if lastchar is newline:
            if state is echo and char is non-digit:
                state = skip
            else if state is skip and and char is digit:
                state = echo
        if state is echo:
            output char
        lastchar = char
Run Code Online (Sandbox Code Playgroud)

像这样的自定义目标代码有时可以比通用正则表达式处理引擎更高效,因为它可以针对特定情况进行优化.无论这种情况是真的,还是任何情况,都应该测试.我的头号优化口号是衡量,不要猜!