More consistent iteration times

We were doing some quick and dirty load testing the other day, using a simple shell script to load messages into a queue in batches. The code looked something like:

while something ;do
echo Sending messages $(date)
send-messages
some-other-stuff
sleep 5
done

It seemed to be working but every few iterations, the time would skip by 6 seconds instead of 5. Obviously, the time it took to send the messages and do some other stuff was adding up. Since we’re in quick and dirty mode anyway, my first instinct was to run the send-messages asynchronously (the other stuff was printing log output and had to run in sequence), so we just added an & to the end of the send-messages line and the number of skips dropped by about a third.

This was an improvement but we were still skipping pretty often and we realized we could do even better.

Rather than using sleep to add a delay, we realized we could use it to act more like a timer. We started the sleep in the background at the top of the loop body and called wait once the body of the loop was done and ready to pause for the remaining time. It was a simple change:

while something ;do
sleep 5 &
slp=$!
echo Sending messages $(date)
send-messages
some-other-stuff
wait $slp
done

This kept each loop iteration really close to the 5 second goal. We might still see some drift over time but it was good enough for our purposes.