tl;dr use read -t 0.1 -N 0 for delay that small.

1   Why read?

If your script needs an interval to be little more precise, then use builtin read command instead of external sleep command, /bin/sleep or /usr/bin/sleep, which is the default on most system.

When the interval is tiny even like 0.1 seconds, invoking an external command can already show some noticeable runtime overhead, for example:


$ time for ((i=0; i<10; i++)); do /bin/sleep 0.1; done
0m1.024s

That is 2.4% overhead while using read has only 0.1% overhead as shown as follows:


$ time for ((i=0; i<10; i++)); do read -t 0.1 -N 0; done
0m1.001s

Option -N 0 ensures no key press would interrupt the delay except Ctrl+C.

2   Detailed tests

Using the code below to test the elapsed time:


time for ((i=0; i<I; i++)); do $CMD; done

The results are (it’s % overhead in the parentheses):

CMDI=1000I=2000I=3000
/bin/sleep 0.0013.002s (200.2%)6.014s (200.7%)9.026s (200.9%)
read -t 0.001 -N 01.113s (11.3%)2.226s (11.3%)3.339s (11.3%)
builtin sleep 0.0011.129s (12.9%)2.254s (12.7%)3.379s (12.6%)

Note that a portion of overhead is contributed by the loop, for instance, I=10000, CMD=:, elapsed time is about 0.102 seconds. The third command is the builtin sleep for Bash, see builtin sleep.

3   Conclusions

From the results above, it’s pretty clear that the overhead of using external sleep is high and it seems to accumulate as I increases, which means it only gets less iterations within same duration over time.

read or builtin sleep has consistent overhead around 11% or 12%. I was surprised to see builtin sleep takes more time to execute than read.

If your script uses endless loop which utilizes tiny intervals and they are smaller than 0.1 seconds, then you should use read to delay the process instead of using sleep.

Moreover, a few years back, I noticed some strange memory use when endless loop with external commands. External command costs and that makes me port my PS1 into C extension for Bash.

It’s inevitable that you need external commands when writing a Bash script, but when there is a builtin command, use it even it looks bizarre by using read for delay.

4   Builtin sleep

Bash ships a builtin sleep, but it’s not enabled by default, it can be enabled via:


enable -f /usr/lib64/bash/sleep sleep

You might find it by locate on your system if it’s installed in different location.

Bahs’s version of sleep only supports seconds:


sleep: usage: sleep seconds[.fraction]

Less flexible than common sleep command, but it’s more than enough to use in scripting.