Measure performance of a fast bash script?

In programming languages I would typically measure the performance of something relatively fast (<1 second completion) by looping it a few thousand times, and then getting the average time per completion.

How would I do the same in bash to compare the execution performance of two very fast commands?


Solution 1:

It's better to use something like time command.

Bash also has a time built-in, what I'm suggesting is using time binary located at: /usr/bin/time.

For one runtime:

command time -f "\nElapsed: %E \nUser: %U \nSystem: %S \nMemory: %M\n" \
./MyCommand 1> /dev/null

Which outputs:

Elapsed: 0:00.01 
User: 0.00 
System: 0.00 
Memory: 2412
  • command: forces bash to use /usr/bin/time instead of time built-in.

You can use time with a loop to get a "avrage", "min", "max" of a specific resource say memory:

This code will run ./COMMAND commands 1000 times, then prints out the "min, max, avg" of its total (data+stack+text) memory usage.

#!/bin/bash
tmpfile=`mktemp`
for i in {1..1000}; do  command time -ao $tmpfile -f "%K" ./COMMAND 1>/dev/null; done;
awk 'NR == 1 {min = $0} $0 > max {max = $0} {total += $0} END {print total/NR, min, max}' $tmpfile
rm $tmpfile

Here is the output:

2436.89 2524 2324

You can change %K with:

  • %E: Elapsed real time
  • %I: Number of file inputs
  • %P: Percentage of the CPU that this job got
  • %k: Number of signals delivered to the process
  • %U: CPU usage in user mode
  • %S: CPU usage in kernel mode

See man time

Thanks to muru for writing a more clear awk statement.

Solution 2:

You can use Python's timeit module (which is usually used for python code snippets), with the subprocess.call function to run external commands:

$ python3 -m timeit -s 'import subprocess' 'subprocess.call(["sleep", "0.1"])' 
10 loops, best of 3: 103 msec per loop

You can change the number of loops with -n:

$ python3 -m timeit -n 5 -s 'import subprocess' 'subprocess.call(["sleep", "0.1"])' 
5 loops, best of 3: 103 msec per loop

And since sleep 0.1 should sleep for 100 ms, it looks like the measurement is pretty accurate.

Also see:

  • How to use the timeit module on Stack Overflow