12

Given

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;
done

except ksh heroically makes it without forking once:

dash    2
bash    2
zsh     2
ksh     0

How does it do that?


Edit:

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

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

Output:

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. – PSkocik Jun 17 '16 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 – Eric Renouf Jun 17 '16 at 15:06
  • 1
    @EricRenouf Lol, yes I do. And it does stuff, too. ;) – PSkocik Jun 17 '16 at 15:16
  • Answerers may want to read stackoverflow.com/questions/14686872 . – JdeBP Jun 17 '16 at 15:54
13

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...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.