Timing Time in Bash

As someone who uses bash all the time, I got used to $EPOCHSECONDS as a source of time. As a shell variable, it’s probably the fastest way to get that information. That said, getting down to using date is still something I occassionally do. It’s supported accross the shells and it’s still fast enough.

But, I started wondering - what is the speed difference? As an example I decided to use SECONDS % 60 as it’s not only getting seconds but also processing them a bit. I would say that is a representative usage of the time - not just reading but also adding some light arithmetic operation. So, I prepared a script to execute the following:

echo $EPOCHREALTIME
echo $((EPOCHSECONDS %60))
echo $EPOCHREALTIME
printf '%(%S)T\n'
echo $EPOCHREALTIME
echo $(date +%S)
echo $EPOCHREALTIME

On bash this will run my three equivalent examples of how to get a number of seconds and get their execution time in microseconds. Yes, echo here is bluring results a bit but it’s bluring them for all examples the same. For a quick test, it’s good enough. So, I placed this into a 100x loop and here are the results.

CommandAverageStDevRatio
echo $((EPOCHSECONDS %60))0.0000380.0000141.00
printf '%(%S)T\n'0.0001110.0000362.95
echo $(date +%S)0.0046540.000726123.78

As expected, using $EPOCHSECONDS is the fastest. I am slightly surprised that printf is 3x slower. I guess it makes sense because it is doing additional parsing, but I expected the result to be closer. But both of those are in microseconds on my laptop.

The only test to reach the milliseconds was date. Invoking date was 42x slower than printf and almost 124x slower than using the variable directly. Now, while this looks dreadful in comparison, in reality it’s not that bad as this doesn’t mean CPU was busy for the duration. But I find it still a bit worrying considering how often I used it myself.

But let’s be realistic - you are not echoing date command. You are probably just storing it into variable - what is the effect then?

echo $EPOCHREALTIME
TEST=$((EPOCHSECONDS %60))
echo $EPOCHREALTIME
printf -v TEST '%(%S)T'
echo $EPOCHREALTIME
TEST=$(date +%S)
echo $EPOCHREALTIME

Well, this run resulted in the following table.

CommandAverageStDevRatio
TEST=$((EPOCHSECONDS %60))0.0000180.0000071.00
printf -v TEST '%(%S)T'0.0000930.0000235.17
TEST=$(date +%S)0.0040760.000451226.58

Times did reduce a bit, especially for printf, but the ratios got even worse.

In the end, if you need to deal with a local time zone or you need a POSIX shell, date is still worth it. But, for bash-specific scripts, I will start paying a bit more attention to use EPOCHSECONDS when I can.