流水线sed调用和多个sed表达式之间的效率是否存在差异?

Zac*_*ack 5 regex bash performance sed

我对bash中的sed效率有疑问.我有一系列流水线的sed语句,例如:

var1="Some string of text"

var2=$(echo "$var1" | sed 's/pattern1/replacement1/g' | sed 's/pattern2/replacement2/g' | sed 's/pattern3/replacement3/g' | sed 's/pattern4/replacement4' | sed 's/pattern5/replacement5/g')
Run Code Online (Sandbox Code Playgroud)

假设没有输入依赖于早期sed管道的编辑输出,我最好用表达式语句编写上面的脚本吗?例如:

var2=$(echo "$var1" | sed -e's/pattern1/replacement1/g' -e's/pattern2/replacement2/g' -e's/pattern3/replacement3/g' -e's/pattern4/replacement4/g' -e's/pattern5/replacement5/g')
Run Code Online (Sandbox Code Playgroud)

这里有效率吗?

Tod*_*obs 9

简答

使用多个表达式比使用多个管道更快,因为在创建管道和分叉sed进程时会有额外的开销.然而,在实践中很少有差异.

基准

使用多个表达式比多个管道更快,但对于平均用例可能不够重要.使用你的例子,执行速度的平均差异只有千分之二秒,这还不足以令人兴奋.

# Average run with multiple pipelines.
$ time {
    echo "$var1" | 
    sed 's/pattern1/replacement1/g' |
    sed 's/pattern2/replacement2/g' |
    sed 's/pattern3/replacement3/g' |
    sed 's/pattern4/replacement4/g' |
    sed 's/pattern5/replacement5/g'
}
Some string of text

real        0m0.007s
user        0m0.000s
sys         0m0.004s
Run Code Online (Sandbox Code Playgroud)
# Average run with multiple expressions.
$ time {
    echo "$var1" | sed \
    -e 's/pattern1/replacement1/g' \
    -e 's/pattern2/replacement2/g' \
    -e 's/pattern3/replacement3/g' \
    -e 's/pattern4/replacement4/g' \
    -e 's/pattern5/replacement5/g'
}
Some string of text

real        0m0.005s
user        0m0.000s
sys         0m0.000s
Run Code Online (Sandbox Code Playgroud)

当然,这不是针对大型输入文件,数千个输入文件或在具有数万次迭代的循环中运行的测试.尽管如此,似乎可以肯定地说,这种差异很小,足以与大多数常见情况无关.

不寻常的情况是另一回事.在这种情况下,基准测试将帮助您确定使用内联表达式替换管道是否是针对该用例的有价值的优化.


gho*_*oti 6

sed 中的大部分开销往往是处理正则表达式,但您在每个示例中处理相同数量的正则表达式。

考虑到操作系统需要为管道的每个元素构造 std 和 stdout。Sed 还占用系统中的内存,操作系统必须为 sed 的每个实例分配该内存——无论是一个实例还是四个实例。

这是我的评估:

$ jot -r 1000000 1 10000 | time sed 's/1/_/g' | time sed 's/2/_/g' | time sed 's/3/_/g' | time sed 's/4/_/g' >/dev/null 
        2.38 real         0.84 user         0.01 sys
        2.38 real         0.84 user         0.01 sys
        2.39 real         0.85 user         0.01 sys
        2.39 real         0.85 user         0.01 sys
$ jot -r 1000000 1 10000 | time sed 's/1/_/g;s/2/_/g;s/3/_/g;s/4/_/g' >/dev/null
        2.71 real         2.57 user         0.02 sys
$ jot -r 1000000 1 10000 | time sed 's/1/_/g;s/2/_/g;s/3/_/g;s/4/_/g' >/dev/null
        2.71 real         2.56 user         0.02 sys
$ jot -r 1000000 1 10000 | time sed 's/1/_/g;s/2/_/g;s/3/_/g;s/4/_/g' >/dev/null
        2.71 real         2.57 user         0.02 sys
$ jot -r 1000000 1 10000 | time sed 's/1/_/g;s/2/_/g;s/3/_/g;s/4/_/g' >/dev/null
        2.74 real         2.57 user         0.02 sys
$ dc
.84 2* .85 2* + p
3.38
$ 
Run Code Online (Sandbox Code Playgroud)

从 3.38 > 2.57 开始,如果您使用 sed 的单个实例,则会占用更少的时间。