我试图理解这两个类似命令之间的差异。
aa=$(foo | bar | head -1)
read aa < <(foo | bar | head -1)
<()
需要#!/bin/bash
,但这会让它变慢吗?bash
或sh
流程吗?我希望使用性能最佳的命令。
答案 0 :(得分:7)
lastpipe
,则每个管道元素都有一个进程加上替换加上父进程的子shell。lastpipe
,管道的最后一个元素将exec
在两种情况下都不会分叉,仍然需要相同数量的进程。/dev/fd/*
的系统上编译shell,shell将为进程替换创建命名管道。这可能会影响绩效。$(<...)
除外)。在mksh和ksh93中,还有${ ;}
样式命令替换,但每个shell实现的方式不同。在ksh93中,它可能会也可能不会加速。在mksh,可能不是。 mksh不支持进程替换,并且zsh不支持(并且无法模拟)BASHPID
,所以我没有调查它。命令替换本质上没有什么比Bash中的进程替换更快,但head
在read
的情况下是多余的,因为你只在那里读取一行。另外,始终使用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;一起使用的过程替换信息。同样。