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

标签 linux bash grep cut cat

我设置了一个非常长且复杂的 shell 管道来获取 2.2Gb 的数据并进行处理。目前处理需要 45 分钟。管道是一些捆绑在一起的 cut、grep、sort、uniq、grep 和 awk 命令。我怀疑是 grep 部分导致它花费这么多时间,但我无法确认。

有没有办法从头到尾“剖析”整个管道以确定哪个组件最慢以及它是否受 CPU 或 IO 限制,以便对其进行优化?

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

grep -v ^[0-9]

最佳答案

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

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

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

  • 0.304 (0.004 + 0.300) 秒;
  • 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) 秒用于排序

这告诉我要研究的主要内容是 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

像这样的自定义、有针对性的代码有时可以比通用正则表达式处理引擎更高效,原因很简单,因为它可以针对特定情况进行优化。无论是这种情况还是任何 情况都是如此,您都应该测试一下。我的第一条优化口号是测量,不要猜测!

关于linux - 如何确定我的 shell 管道中最慢的组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7712770/

相关文章:

php - UTF-8贯穿始终

linux - 如何在 Bash 中使一组命令超时

linux - aws firecracker 如何处理 vcpu?

linux - 在管道 awk 输出上打印循环输入文件名

linux - 使用 grep 搜索以 's' 开头并以 '.conf' 结尾的所有文件

linux - Windows下无法运行Laravel Homestead(grep报错)

linux - expect script + fit expect 以防不需要密码

string - Bash 索引第 n 个字符后的子字符串

ubuntu - ack(ack-grep) 忽略嵌套目录

vim - 是否可以在 Vim 中 grep 快速修复窗口?