17

我试图了解这两个类似命令之间的区别。

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

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

4

4 回答 4

8
  1. 不,Bash 在非 POSIX 模式下更快。
  2. 这取决于。这既是特定于实现的细节,也是特定于平台的细节。
    • 在 Bash 中,两者都需要相同数量的进程。如果lastpipe未启用,则每个管道元素都有一个进程,外加一个用于替换的子外壳和父进程。
    • 在 Bash 中,如果lastpipe启用,管道的最后一个元素exec在两种情况下都不会分叉,仍然需要相同数量的进程。
    • 在 ksh93 中,在这种情况下,两者都需要相同数量的进程,但如果最后一个管道元素是内置的,它将在父进程中运行以进行命令替换,从而使其更快。
    • 在 Bash 和 ksh93 中,如果 shell 在不支持的系统上编译/dev/fd/*,则 shell 将创建命名管道来代替进程。这可能会影响性能。
  3. 上一个子弹也许应该放在这里。注意“subshel​​l”并不一定意味着一个单独的进程,尽管在几乎所有的 shell 中,它确实($(<...)除了支持它的 Bash 之外的所有东西)。在 mksh 和 ksh93 中,也有${ ;}样式命令替换,但每个 shell 以不同的方式实现这一点。在 ksh93 中,它可能会或可能不会提供加速。在 mksh 中,可能不是。mksh 不支持进程替换,zsh 不支持(也没有办法模拟)BASHPID,所以没研究。

命令替换本质上没有什么比 Bash 中的进程替换更快的了,但是head在这种情况下是多余的,read因为你在那里只读取一行。顺便说一句,始终使用head -n ...---1不可移植。此外,除非您希望 shell 破坏输入,否则不要使用readwithout 。-r

于 2013-03-14T19:03:44.130 回答
3

在这里提高性能的最好方法是尽可能地摆脱前叉和管道。

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

于 2013-03-14T18:13:17.947 回答
2

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

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

bash -c 'time PIPELINE...'

两者都创建shell——在第一种情况下,shell 读取和扩展子shell 的输出,而read在第二种情况下,shell 的内置读取来自后台进程。

看:

于 2013-03-14T17:58:44.187 回答
1

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

查看与“tee”一起使用的过程替换的信息。

http://mywiki.wooledge.org/ProcessSubstitution

于 2013-03-14T18:27:26.223 回答