cmd='fun(){ echo "$@";  }; fun $(fun $(fun hi))'

shells tend to need to make 2 forks to make it happen

strace-f(){ strace -f "$@" 2>&1; }; 
for sh in dash bash zsh ksh; do 
    printf "$sh\t" ; strace-f $sh -c "$cmd"  |grep -e clone -e fork -c;

except ksh heroically makes it without forking once:

dash    2
bash    2
zsh     2
ksh     0

How does it do that?


Here's how it goes down with a pipe thrown in:

cmd='fun(){ echo "$@"| echo "$@";  }; fun $(fun $(fun hi))'


dash    11
bash    10
zsh     5
ksh     3 
  • It fails doesn't manage this for whole pipelines though. I would like to make this possible for whole pipelines, prossibly bring it to other shells. Jun 17, 2016 at 15:02
  • 3
    Just for sanity checking, do you have ksh installed? When I run your code I get 0 for any shell I don't have installed Jun 17, 2016 at 15:06
  • 1
    @EricRenouf Lol, yes I do. And it does stuff, too. ;) Jun 17, 2016 at 15:16
  • Answerers may want to read stackoverflow.com/questions/14686872 .
    – JdeBP
    Jun 17, 2016 at 15:54

1 Answer 1


Ksh93 does a lot to avoid forks. I have no idea how it knows how to handle the first case, as a truss shows that it only calls one write(2) call with the final result.

It may be that David scans the command in macro.c and knows that he may handle "echo" internally.

What I can say is that I rewrote the parser and the interpreter of the "Bourne Shell" last year and mainly reduced the number of forks and replaced many of the forks by vfork() calls. This currently makes the Bourne Shell the second fastest shell past ksh93. You may like to run your tests with bosh as well.

BTW: ksh93 avoids forks in general. It implements a structure that contains all previous global variables and this made the shell code reentrant if it is called with different instances of the "global" variable structure pointer.

This method is used by ksh93 whenever there is a (cmd) subshell.

The reason for this rewrite is that David is using Win-DOS on his laptop and he did not like the slow Cygwin, so he wrote UWIN and uses ksh93 on Win-DOS directly. As there is no fork() on Win-DOS, he needed to find a new solution...

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .