Debian的Bash手册建议在需要$(< file)
时使用特殊命令替换$(cat file)
,以提高性能,避免执行外部二进制文件。
但是,以下代码的测量完成时间大致相同:
time for i in {0..1000}; do echo str | { in=$(cat); }; done
time for i in {0..1000}; do echo str | { in=$(< /dev/fd/0); }; done
在几次运行中,他们分别围绕这些数字一致地返回值:
real 0m3.665s
user 0m0.365s
sys 0m0.782s
和
real 0m2.401s
user 0m0.233s
sys 0m0.533s
因此,对于大多数用例,cat
上的命令替换的改进在很大程度上可以忽略不计。由于我的脚本需要快速循环读取大量的标准输出,我该怎么做才能加快这些读数?特别是,需要将整个stdin数据流转储到Bash变量中以进行进一步的参数替换。
进一步测试:
在下面的评论和进一步测试之后,我设置10,000次迭代而不是1000次以最小化管道设置开销,并删除了复合命令语法的括号:
$ time for i in {1..10000}; do echo str | in=$(cat); done
real 0m24.754s
user 0m6.958s
sys 0m18.996s
$ time for i in {1..10000}; do echo str | in=$(< /dev/fd/0); done
real 0m33.913s
user 0m3.736s
sys 0m10.516s
在这里,我无法解释为什么$(< /dev/fd/0)
现在更慢。
答案 0 :(得分:3)
您忘记了与从stdin读取无关的性能成本(fork()创建子shell的成本,设置管道,等待()等待这些进程退出等等)。
$ time for i in {0..1000}; do echo str | { in=$(cat); }; done
real 0m3.183s
user 0m1.427s
sys 0m2.486s
$ time for i in {0..1000}; do echo str | { in=$(< /dev/fd/0); }; done
real 0m1.973s
user 0m0.917s
sys 0m1.844s
$ time for i in {0..1000}; do echo str | true; done
real 0m1.294s
user 0m0.708s
sys 0m1.367s
因此:
$(cat)
增加了大约(3.183s - 1.294s == 1.889s)挂历时间超过1000次迭代,与执行所有其他设置但不读取stdin的代码相比。$(</dev/fd/0)
在1000次迭代中增加了大约(1.972s - 1.294s == 0.697s)。这是一个2.7倍的改进,远低于你期望的每次调用1ms。