Unfortunately, running exit is not a great strategy for running benchmarks. As an example, for zsh specifically, plugin managers are optimized for fast exit.
romkatv did a great write-up and benchmark within the context of zsh[0]. It's a great read.
> Interestingly, because /bin/sh sets $SHELL, fish doesn’t change that value, so my fish shell reports /bin/sh as the value for $SHELL
Fish actually doesn’t write to (or directly use?) $SHELL at all, as it doesn’t consider it part of the shell’s contract to do so. At least if I’m not misremembering.
> The environment variable values for $HOME, $USER, $SHELL, $PATH, $LOGNAME, and $MAIL are set according to the appropriate fields in the password entry.
Anybody know if it's possible to build a bash without unicode/locale support? The majority of the difference in bash/dash speed is erased by setting LC_ALL=C, but that, of course, will affect other programs as well.
I tried with --disable-translatable-strings and got a modest speedup; --disable-multibyte failed to compile, and I didn't see any other obvious options to try.
[edit] Runs below:
$ hyperfine -N "dash -c exit"
Benchmark 1: dash -c exit
Time (mean ± σ): 0.8 ms ± 0.0 ms [User: 0.4 ms, System: 0.3 ms]
Range (min … max): 0.7 ms … 1.1 ms 3011 runs
Warning: The first benchmarking run for this command was significantly slower than the rest (1.0 ms). This could be caused by (filesystem) caches that were not filled until after the first run. You should consider using the '--warmup' option to fill those caches before the actual benchmark. Alternatively, use the '--prepare' option to clear the caches before each timing run.
$ hyperfine -N "bash -c exit"
Benchmark 1: bash -c exit
Time (mean ± σ): 4.6 ms ± 0.2 ms [User: 3.3 ms, System: 1.2 ms]
Range (min … max): 4.3 ms … 5.3 ms 596 runs
Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.
$ LC_ALL=C hyperfine -N "bash -c exit"
Benchmark 1: bash -c exit
Time (mean ± σ): 1.7 ms ± 0.0 ms [User: 0.7 ms, System: 0.9 ms]
Range (min … max): 1.6 ms … 2.1 ms 1446 runs
Warning: The first benchmarking run for this command was significantly slower than the rest (2.1 ms). This could be caused by (filesystem) caches that were not filled until after the first run. You should consider using the '--warmup' option to fill those caches before the actual benchmark. Alternatively, use the '--prepare' option to clear the caches before each timing run.
There are some interesting assertions in this article.
"bash and zsh are fairly fast" - the manual page for bash (confirmed up to v5.1.8) contains "It's too big and too slow" under the BUGS section near the end of the document. The dash shell is rumored to be 4x as fast as bash for many uses.
"Both ksh and dash are too bare-bones for me to want to use them as an interactive shell" - dash can actually be compiled with full editing of the command line, but is rarely prepared in this way. While dash omits almost all features that are not in the POSIX standards, it can in fact be used well as a standards-compliant interactive shell. The Korn shell also has a much larger feature set and is the default interactive shell on commercial UNIX; the last version released by David Korn has vastly more capability and features than bash.
"exec fish" - this is a bit dangerous, in that a mistake will prevent an interactive login. To fix such a case, use SFTP to push corrections. If you really like fish, ensure that it's added to the /etc/shells file, then use the chsh command to make it your login shell.
That "too big and slow" comment in bash manpage is very out of date. For example I've did a local test and "bash" is about 4x slower than "dash".. but still only 1.5 ms, and that would be certainly be fast enough for most applications.
> The dash shell is rumored to be 4x as fast as bash for many uses.
That seems a lot, and sounds like those rumours are exactly that. When Debian switched from bash to dash as /bin/sh they saved about 5% on boot time (pre-systemd) on a slow EEE "netbook" thingy.
Maybe there are some specific usage patterns that give a 4x speed-up? I don't know. That doesn't seem to be the common case though.
That "it's too big and slow" message has been there since at least 1996 by the way, the first entry in git ("Imported from ../bash-1.14.7.tar.gz").
It's not incorrect as that was what was observed. It's a real-world use case.
Some artificial benchmarks doesn't automatically translate to "4x as fast as bash for many uses".
Things like "500k variable assignments per second" vs. "1.8M variable assignments per second" is an insignificant and unmeasurable difference for most real-world scripts because they have dozens, hundreds, or perhaps thousands of assignments. Not millions. For most scripts the majority of time is spent launching binaries and doing whatever that external binary is doing.
David Korn's ksh93 was passed on to a new set of developers, who attempted to release a new version; AT&T rolled back these changes due to performance problems which raised questions of support status. It does appear that ksh93 development has resumed, and a new version was released late last year.
My recollection is that someone adopted the ksh93 tree and started making incompatible changes, which were picked up by some distributions (Debian I know) and broke things.
I use ksh93 as my primary shell, interactively and for personal scripts. For scripting, a killer feature is the declarative `getopts` that makes it trivial for even the quickest dirtiest script to have full command line option handling including help.
Someone in the arch community did benchmarks on many shells a year or 2 ago. It was very well written. The end result was ksh93 was the fastest.
I really wish I had the link, but I lost it. I have looked for it many times but without luck. Looking again but I doubt I will find it. If I do I will update this post.
I believe this is the link, but I cannot get to it due to some cloud ways error.
romkatv did a great write-up and benchmark within the context of zsh[0]. It's a great read.
[0] https://github.com/romkatv/zsh-bench#how-not-to-benchmark