Bash GNU/Linux Shell

Hide in Bash

Oops! why is my Bash shell script running so slow?

When debugging a Bash shell script, we may find that it runs slowly. Therefore, it's important to know some of the details hidden in Bash and learn some tricks.

In the bash shell, we need to avoid frequent use of `` or $() in shell scripts.

`` and $() create a subshell to run the list of commands enclosed by them.[a] The subshell is a copy of a shell process.[b] That is, `` and $() spawn a new process in the OS and the parent shell has to hang and wait for the new process to exit. So comes the critical problem, spawning process (1) is very time-consuming.

Let me verify my claim with the following demos.

Write 0 - 99 to file test.tmp without `` and $().

# !/bin/bash

cat /dev/null > test.tmp

function func() {
        echo -n $1 >> test.tmp
}

for (( i=0; i < 100; i++)); do
        func $i
done

Time consumed in executing shell scripts.

time ./test.sh

real    0m0.004s
user    0m0.003s
sys     0m0.000s
cat test.tmp
0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899

Write 0 - 99 to file test.tmp with ``.

# !/bin/bash

cat /dev/null > test.tmp

function func() {
        echo -n $1 >> test.tmp
}

for (( i=0; i < 100; i++)); do
        a=`func $i`
done

We can see that the time consumed is greater than the time consumed in Demo 1.

time ./test.sh

real    0m0.068s
user    0m0.053s
sys     0m0.010s
cat test.tmp
0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899

Of course, the Bash shell provides a way to get the current shell process ID. This is the BASHPID variable [c]. The following demo uses BASHPID to confirm that a new process has been spawned when `` is used.

# !/bin/bash

function func() {
        echo $BASHPID>pid.tmp
}

b=`func $i`

echo current PID: $BASHPID
echo subshell PID: `cat pid.tmp`

As we can see, the PIDs are not the same.

./test.sh 
current PID: 14485
subshell PID: 14486

(1) todo: Introduce what happens when a process is spawned.
[a] 3.5.4 Command Substitution. In Bash Reference Manual. 5.2. 2022.
[b] 3.7.3 Command Execution Environment. In Bash Reference Manual. 5.2. 2022.
[c] 5.2 Bash Variables. In Bash Reference Manual. 5.2. 2022.
L P A F P