命令替换与进程替换

时间:2013-03-14 17:47:52

标签: bash command-substitution process-substitution

我试图理解这两个类似命令之间的差异。

aa=$(foo | bar | head -1)
read aa < <(foo | bar | head -1)
  • 我知道<()需要#!/bin/bash,但这会让它变慢吗?
  • 他们是否创造了相同数量的子壳?
  • 他们需要相同数量的bashsh流程吗?

我希望使用性能最佳的命令。

4 个答案:

答案 0 :(得分:7)

  1. 否。 Bash在非POSIX模式下更快。
  2. 这取决于。这是特定于实现和特定于平台的细节。
    • 在Bash中,两者都需要相同数量的进程。如果未启用lastpipe,则每个管道元素都有一个进程加上替换加上父进程的子shell。
    • 在Bash中,如果启用lastpipe,管道的最后一个元素将exec在两种情况下都不会分叉,仍然需要相同数量的进程。
    • 在ksh93中,两者在这种情况下都需要相同数量的进程,但如果最后一个管道元素是内置的,它将在父进程中运行以进行命令替换,从而使其更快。
    • 在Bash和ksh93中,如果在不支持/dev/fd/*的系统上编译shell,shell将为进程替换创建命名管道。这可能会影响绩效。
  3. 以前的子弹也许应该在这里。注意“subshel​​l”并不一定意味着一个单独的进程,尽管在几乎所有的shell中都是如此(除了支持它的Bash之外的所有内容中都有$(<...)除外)。在mksh和ksh93中,还有${ ;}样式命令替换,但每个shell实现的方式不同。在ksh93中,它可能会也可能不会加速。在mksh,可能不是。 mksh不支持进程替换,并且zsh不支持(并且无法模拟)BASHPID,所以我没有调查它。
  4. 命令替换本质上没有什么比Bash中的进程替换更快,但headread的情况下是多余的,因为你只在那里读取一行。另外,始终使用head -n ... - -1不可移植。另外,除非您希望shell破坏输入,否则不要在没有read的情况下使用-r

答案 1 :(得分:3)

提高性能的最佳方法是尽可能多地摆脱叉子和管道。

出于所有意图和目的,您不应该担心所述的性能问题。 99%的执行时间可能由特定命令决定,而不是由进程替换与命令替换的差异决定。你知道优化的第一定律吗?别。特别是如果你牺牲了便携性。使用$(whatever)并忘记其他所有内容。如果你真的担心性能,那么你需要解决的是命令/管道/分支。否则你会试图通过挤压眼泪来减肥。

答案 2 :(得分:2)

使用Bash's内置time进行基准测试,第一种形式比第二种形式慢。

您可以使用以下方式自行测试:

bash -c 'time PIPELINE...'

创建子shell - 使用shell读取并扩展第一种情况下子shell的输出,以及shell的read内置读取来自第二种情况的后台进程。 / p>

请参阅:

答案 3 :(得分:1)

进程替换绕过由piplines /命令替换创建的子shell。替换语法由FIFO或FD的名称替换,其中的命令在后台运行。 替换同时执行作为参数扩展和命令替换。

查看与&#34; tee&#34;一起使用的过程替换信息。同样。

http://mywiki.wooledge.org/ProcessSubstitution