2013-03-14 99 views
10

我想了解这两个类似命令之间的差异。命令替换vs进程替换

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

我正在寻找使用最佳性能的命令。

回答

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

没有什么本质上快约比猛砸一个进程替换命令替换,但head是在read的情况下,多余的,因为你只是读一行在那里。顺便说一句,总是使用head -n ... - -1是不便携的。另外,除非您希望外壳破坏输入,否则不要使用read而不使用-r

2

Benchmarking与Bash's内置time,第一种形式比第二种形式慢。

你可以测试它自己:

bash -c 'time PIPELINE...' 

两个创建子shell - 从背景壳阅读和扩大其在第一种情况下一个子shell的输出,与外壳的read内置阅读第二个过程。

参见:

+1

嗯,这个说法并不完全正确。希望你不介意我已经为你调整了一下。在这两种情况下都有“文件描述符”,并且两者都会生成一个子shell,至少在Bash中也总是暗含至少一个分支。在我的更广泛的测试中,“read -rx <(...)'”和“'x = $(...)'”之间的区别几乎无法用小输入迭代,对于单个大输入,分配的速度稍快(与预期的一样),但在最初的问题中,两种解决方案都是奇数和次优的。 – ormaaj 2013-03-14 20:48:45

+0

没问题'兄弟,感谢编辑。 – 2013-03-15 00:31:14

1

在这里提高性能的最佳方式是让尽可能多的,你可以摆脱叉子和管道。

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

1

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

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

http://mywiki.wooledge.org/ProcessSubstitution