bashcommand-substitutionprocess-substitution

Command substitution vs process substitution


I am trying to understand the differences between these two similar commands.

aa=$(foo | bar | head -1)
read aa < <(foo | bar | head -1)

I am looking to use the command with the best performance.


Solution

    1. No. Bash is faster in non-POSIX mode.
    2. It depends. This is both an implementation-specific and platform-specific detail.
      • In Bash, both require the same number of processes. If lastpipe is not enabled, there is a process for each pipeline element plus a subshell for either substitution plus the parent process.
      • In Bash, if lastpipe is enabled, the last element of the pipeline will exec without forking in both cases, still requiring the same number of processes.
      • In ksh93, both should require the same number of processes in this case, but if the last pipeline element were a builtin, it would run in the process of the parent for the command substitution, making it even faster.
      • In both Bash and ksh93, if the shell is compiled on a system that does not support /dev/fd/*, the shell will create named pipes for process substitutions instead. This likely affects performance.
    3. The previous bullet should go here perhaps. Note "subshell" doesn't necessarily imply a separate process, though in almost all shells, it does (with the exception of $(<...) in everything except Bash that supports it). In mksh and ksh93, there's also the ${ ;} style command substitution, but each shell implements this differently. In ksh93, it may or may not give a speedup. in mksh, probably not. mksh doesn't support process substitutions, and zsh doesn't support (and has no way of simulating) BASHPID, so I haven't looked into it.

    There is nothing intrinsically faster about a command substitution than a process substitution in Bash, but the head is redundant in the case of read since you're only reading a single line there. As an aside, always use head -n ... -- -1 is not portable. Also, don't use read without -r unless you want the shell to mangle the input.