How to measure elapsed time in bash

Last updated on March 9, 2021 by Dan Nanni

Elapsed time is the amount of wall-clock time that has passed between the beginning and the end of a particular event. In other words, elapsed time is a measurement of actual time taken for the event to complete. It is common to to measure elapsed time as part of application performance analysis and profiling. While you are working on a bash script, you may also want to add instrumentation in your script to calculate elapsed time for various components (e.g., a bash function, an external command, etc). In this tutorial, let's find out how to measure elapsed time in a bash script.

The most common way to measure elapsed time in bash is to utilize the date command, which can show the current system date and time in a configurable format. Using the flexiblity of date's display format, you can easily calculate elapsed time with different resolutions.

Measure Elapsed Time in Seconds in Bash

When you call date with +%s option, it shows the current system clock in seconds since 1970-01-01 00:00:00 UTC. Thus, with this option, you can easily calculate time difference in seconds between two clock measurements.

start_time=$(date +%s)
# perform a task
end_time=$(date +%s)

# elapsed time with second resolution
elapsed=$(( end_time - start_time ))

Another (preferred) way to measure elapsed time in seconds in bash is to use a built-in bash variable called SECONDS. When you access SECONDS variable in a bash shell, it returns the number of seconds that have passed so far since the current shell was launched. Since this method does not require running the external date command in a subshell, it is a more elegant solution.

start_time=$SECONDS
sleep 5
elapsed=$(( SECONDS - start_time ))
echo $elapsed

This will display elapsed time in terms of the number of seconds. If you want a more human-readable format, you can convert $elapsed output as follows.

eval "echo Elapsed time: $(date -ud "@$elapsed" +'$((%s/3600/24)) days %H hr %M min %S sec')"

This will produce output like the following.

Elapsed time: 0 days 13 hr 53 min 20 sec

Measure Elapsed Time in Milliseconds in Bash

To measure elapsed time with millisecond resolution, use date with +%s.%3N option, which returns the current time in milliseconds. Since bash does not support floating point arithmetic, you need to rely on an external calculator tool such as bc to compute time difference with millisecond resolution. The bc calculator allows you to specify the precision of floating point numbers (i.e., number of digits after floating point) with scale variable. Thus, with scale=3, bc computes time difference with millisecond resolution.

start_time=$(date +%s.%3N)
# perform a task
end_time=$(date +%s.%3N)

# elapsed time with millisecond resolution
# keep three digits after floating point.
elapsed=$(echo "scale=3; $end_time - $start_time" | bc)

Measure Elapsed Time in Microseconds or in Nanoseconds in Bash

Technically it is possible to calculate elpased time with a higher resolution such as microsecond-level or nanosecond-level using date command, since date can show current time in nanosecond resolution. However, such high-resolution elapsed time measurements with date command will not be anywhere near accurate due to the variable cost of invoking the external date command in a subshell.

As a simple illustration, let's run the following bash script to measure elapsed time of noop (i.e., do nothing) with microsecond resolution.

while : ; do
    start_time=$(date +%s.%6N)
    : # do nothing
    end_time=$(date +%s.%6N)

    elapsed=$(echo "scale=6; $end_time - $start_time" | bc)
    echo $elapsed
done
.002829
.002890
.002664
.002456
.002395
.002451
.002397
.002401
.002373
.002449
.002457
.002475
.002753
.002357
.002420
.002442
.002451
.002449

As you can see above, elapsed time for the same operation (i.e., do nothing) does not remain constant on microsecond-level. This proves that any sub-milliseond-level elapsed time measurement based on an external command will be highly misleading.

If you know of any trick that can improve the accuracy of elapsed time measurement in bash, feel free to share it in the comment.

If you find this tutorial helpful, I recommend you check out the series of bash shell scripting tutorials provided by Xmodulo.

Support Xmodulo

This website is made possible by minimal ads and your gracious donation via PayPal (Credit Card) or Bitcoin (1M161JGAkz3oaHNvTiPFjNYkeABox8rb4g).

Please note that this article is published by Xmodulo.com under a Creative Commons Attribution-ShareAlike 3.0 Unported License. If you would like to use the whole or any part of this article, you need to cite this web page at Xmodulo.com as the original source.

Xmodulo © 2021 ‒ AboutWrite for Us ‒ Feed ‒ Powered by DigitalOcean