我试图了解何时使用" unix工具" vs BASH能力。让我们举个例子,我想根据一些分隔符将字符串分成两部分。使用" cut"调用某种进程/线程/外部处理,这通常比使用其他一些内置的BASH实用程序慢#34;把一个字符串分成两半,不管是什么?
答案 0 :(得分:7)
调用外部工具会导致严重的性能损失。
让我们自己测试一下,将cut
的10,000次迭代与参数扩展的10,000次迭代进行比较:
# for me, this is ~50s wall-clock
time for ((i=0; i<10000; i++)); do
in_str='hello:world'
cut -d: -f2 <<<"$in_str" # External tool!
done >/dev/null
... ... VS
# for me, this is ~0.2s wall-clock
time for ((i=0; i<10000; i++)); do
in_str='hello:world'
printf '%s\n' "${in_str#*:}" # Builtin!
done >/dev/null
复制并粘贴这两者,并查看结果的不同之处。 :)
在我的系统上,内置版本运行时间不到一秒,而外部版本运行大约需要50秒。因此,我们大约在8个基数2个数量级。
现在,对于概念理解 - 要理解的关键事项之一是内置中涉及的所有工作都是在bash内部执行的,而外部工具需要大量的开销来调用: / p>
fork()
关闭bash流程的第二个副本execve()
用所需外部可执行文件的副本替换该新进程(通常需要操作系统调用其链接器和加载器来启动动态二进制文件)wait()
完成该流程...并且,如果您正在捕获输出,则还需要创建FIFO并从中读取。因此,启动外部工具的行为通常比该工具执行其所需功能所花费的时间要慢得多。
那就是说 - 如果你很专注,你可能已经注意到这构造了cut
的最坏情况,每次调用只处理一行输入。结果将是非常不同的:
# for me, this is ~0.12s wall-clock
time for ((i=0; i<10000; i++)); do
printf '%s\n' 'hello:world'
done | cut -d: -f2 >/dev/null
...其中只有一个cut
的调用用于整个流,将启动时间分散到非常多的输入行。
如果作业涉及处理批量输入,而不是一次处理一行,则正确使用外部工具可以更有效。
答案 1 :(得分:1)
基于this documentation, builtins的执行速度比外部命令要快,后者通常需要分离一个单独的进程,所以如果你非常关心性能,你应该在使用内置函数时执行你可以,虽然我们正在谈论分叉过程的时间顺序的改进。
这通常仅在您在紧密循环中多次运行相同命令时才有意义,而不是使用单个命令处理整个输入。
另外需要注意的是,如果您不小心对机器进行了叉式轰炸,您将无法再运行新进程,但您可以运行kill
之类的内置程序来尝试恢复。< / p>
答案 2 :(得分:0)
速度不是bash的卖点,也不是unix工具。 Builtins更快。也就是说,bash应该像急救箱一样使用:当你需要现在和快速的东西时使用它。如果你的脚本开始变得越来越复杂并且你开始关注速度,你应该去更强大的东西,比如Python。