我试图了解这两个类似命令之间的区别。
aa=$(foo | bar | head -1)
read aa < <(foo | bar | head -1)
- 我知道这
<()
需要#!/bin/bash
,但这会使其变慢吗? - 他们创建相同数量的子壳吗?
- 它们是否需要相同数量
bash
或sh
流程?
我希望使用性能最佳的命令。
我试图了解这两个类似命令之间的区别。
aa=$(foo | bar | head -1)
read aa < <(foo | bar | head -1)
<()
需要#!/bin/bash
,但这会使其变慢吗?bash
或sh
流程?我希望使用性能最佳的命令。
lastpipe
未启用,则每个管道元素都有一个进程,外加一个用于替换的子外壳和父进程。lastpipe
启用,管道的最后一个元素exec
在两种情况下都不会分叉,仍然需要相同数量的进程。/dev/fd/*
,则 shell 将创建命名管道来代替进程。这可能会影响性能。$(<...)
除了支持它的 Bash 之外的所有东西)。在 mksh 和 ksh93 中,也有${ ;}
样式命令替换,但每个 shell 以不同的方式实现这一点。在 ksh93 中,它可能会或可能不会提供加速。在 mksh 中,可能不是。mksh 不支持进程替换,zsh 不支持(也没有办法模拟)BASHPID
,所以没研究。命令替换本质上没有什么比 Bash 中的进程替换更快的了,但是head
在这种情况下是多余的,read
因为你在那里只读取一行。顺便说一句,始终使用head -n ...
---1
不可移植。此外,除非您希望 shell 破坏输入,否则不要使用read
without 。-r
在这里提高性能的最好方法是尽可能地摆脱前叉和管道。
出于所有意图和目的,您不应担心所述的性能问题。99% 的执行时间可能由特定命令决定,而不是进程替换与命令替换的差异。你知道优化第一定律吗?不。特别是如果您要牺牲便携性。使用$(whatever)
并忘记其他一切。如果您真的担心性能,那就是您需要解决的命令/管道/分支。否则,你是在试图通过挤出眼中的泪水来减肥。
Bash's
使用内置基准进行基准测试time
,第一种形式比第二种形式慢。
您可以使用以下方法自行测试:
bash -c 'time PIPELINE...'
两者都创建子shell——在第一种情况下,shell 读取和扩展子shell 的输出,而read
在第二种情况下,shell 的内置读取来自后台进程。
看:
进程替换绕过由 piplines/command 替换创建的子 shell。替换语法被替换为 FIFO 或 FD 的名称,其中的命令在后台运行。替换与参数扩展和命令替换同时执行。
查看与“tee”一起使用的过程替换的信息。