Prev: The simplest case, Up: Index, Next: Expansions
External commands
In the previous article we have measured how long it takes to execute one of the simplest commands in UNIX-like systems: /usr/bin/true
. Throughout this part we will refer to this kind of commands as external: they are stored in a standalone binary file somewhere in the filesystem, and can be used in any shell.
time for ((i=0; i<10000; i++)); do
/usr/bin/true
done
real 0m5,829s
user 0m4,226s
sys 0m1,942s
However, we’ve also observed that running such commands involves a number of things the operating system needs to do to run it. Do we really need to load the same shared libraries everytime we call this or that command? Do we need to reach out to the filesystem to load them? Finally, do we always need to start a new process?
Historical shells
The first UNIX shell, written by Ken Thompson was very minimalistic — it supported only command execution, input/output redirection and pipes, thus every command execution involved process creation.
Its successor, Bourne shell, introduced some scripting capabilities in the form of conditional and control flow instructions. It also introduced some simple commands built into the shell, but only those needed to control the script itself (like exit
, wait
, return
). Still commands like true
, false
or test
remained external.
Built-in commands
Since true
, false
and test
are heavily used in conditionals and loops, in order to reduce the overhead of starting a new process on each call, Bash provides their built-in equivalents. Let’s see how they perform in comparison to the external version:
time for ((i=0; i<10000; i++)); do
true # built-in command
done
real 0m0,018s
user 0m0,014s
sys 0m0,004s
Using a built-in command gave us 33x improvement in the execution time and that matches better our intuition about how long it should take.
A similar result we get with the test
command:
-
An external command
time for ((i=0;i<10000;i++)); do /usr/bin/test -z "" done real 0m6,494s user 0m4,718s sys 0m2,148s
-
Built-in command
time for ((i=0;i<10000;i++)); do test -z "" done real 0m0,099s user 0m0,039s sys 0m0,060s
Prev: The simplest case, Up: Index, Next: Expansions