我设置了一个非常长且复杂的 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) 秒用于
排序
。
这告诉我要研究的主要内容是 tail
和 tr
。
很明显,这仅适用于 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/