【问题标题】:Why is $(</dev/fd/0) not much faster than $(cat)?为什么 $(</dev/fd/0) 不比 $(cat) 快多少?
【发布时间】:2015-04-21 17:22:47
【问题描述】:

Debian 的 Bash 手册建议在需要 $(cat file) 时使用特殊的命令替换 $(&lt; 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 的改进在很大程度上可以忽略不计。由于我的脚本需要快速、循环地读取大量标准输入,我可以做些什么来加速这些读取?特别是,需要将整个标准输入数据流转储到 Bash 变量中以进行进一步的参数替换

进一步测试:

在下面的 cmets 和进一步测试之后,我设置了 10,000 次迭代而不是 1000 以最小化管道设置开销,并且我删除了 compound command 语法的括号:

$ 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

这里我无法解释为什么$(&lt; /dev/fd/0) 现在更慢了。

【问题讨论】:

  • 我很困惑。您的基准测试显示了 33% 的加速。
  • ...快速基准测试主要是衡量建立管道所需的时间,而不是读取标准输入的性能。也许如果您向我们展示您的实际代码,我们可以尝试帮助优化它,但事实上,您看到的数字看起来非常合理。
  • 确实如此。即使想使用一种 shell 语言,ksh93(真正的 David Korne ksh,而不是克隆)也快得多。尽管我很鄙视它故意不遵守 POSIX,但 zsh 也是如此。
  • 您认为增加迭代次数如何降低开销?您仍然在每次迭代中设置一次管道,因为管道在您的循环中inside。减少括号是无关紧要的 - 数千个管道的数千个子外壳是昂贵的。
  • 天哪,这是真的!我没有意识到管道是在每次迭代中创建的。在done 之后将管道移出循环,极大地提高了性能。所以是的,管道是一种昂贵的小工具。

标签: performance bash input stdin cat


【解决方案1】:

您忘记考虑与从标准输入读取无关的性能成本(fork()ing 创建子 shell、设置管道、wait()ing 以退出这些进程等的成本)。

$ 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) 在 1000 次迭代中增加了大约 (3.183s - 1.294s == 1.889s) 的挂钟时间。
  • 使用$(&lt;/dev/fd/0) 会增加大约 (1.972s - 1.294s == 0.697s) 超过 1000 次迭代。

这是 2.7 倍的改进,远低于您预期的每次调用 1 毫秒。

【讨论】:

    猜你喜欢
    • 2015-09-15
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-02
    • 2012-08-01
    • 1970-01-01
    相关资源
    最近更新 更多