Posted over 3 years ago. Visible to the public.

Measure elapsed time the right way

Time doesn't move only forwards

Depending on the low level Operating System (OS) settings, Ruby's Time.now uses gettimeofday or clock_gettime Linux functions from time.h.
According to the documentation Archive of gettimeofday it returns a struct with the number of seconds and the system time zone. Ruby VM can then calculate and it returns a Time object with these informations. This is often indicated as wall time in Linux documentation.

However:

The time returned by gettimeofday() is affected by discontinuous jumps in the system time (e.g., if the system administrator manually changes the system time).

The lack of perfect accuracy is due to CPU physical conditions like temperature, air pressure, and even magnetic fields.

So when the OS tries to set a new system time, it doesn't guarantee that the new value will be in the future. If a CPU has a clock that is "too fast", the OS can decide to reset the time of a few seconds backward. Another reason why wall clocks are flawed is because some CPUs can't manage leap seconds.

Elapsed time, the right way

Posix systems have solved this problem by introducing a monotonic clock. It's conceptually similar to a timer that starts with an event and it isn't affected by time floating problems. Each time you request the time to the monotonic clock, it returns the time since that event. On Mac OS, this event is the system boot. Alongside with monotonic, there are several clock types: realtime, monotonic raw, virtual just to name a few. Each of them solves a different problem.

Since Ruby 2.1+ (MRI 2.1+ and JRuby 9.0.0.0+) there is a new method that allows to access to the current values of all these clocks: Process.clock_gettime.
This is named after the Linux function clock_gettime Archive (still from time.h).

Copy
starting = Process.clock_gettime(Process::CLOCK_MONOTONIC) # time consuming operation... ending = Process.clock_gettime(Process::CLOCK_MONOTONIC) elapsed = ending - starting elapsed # => 9.183449000120163 seconds

Owner of this card:

Avatar
Alexander M
Last edit:
over 3 years ago
by Alexander M
Tags:
elapsed, measure, time
Posted by Alexander M to Ruby and RoR knowledge base
This website uses short-lived cookies to improve usability.
Accept or learn more