How do I get elapsed time in milliseconds in Ruby?

Viewed 129602

If I have a Time object got from :

Time.now

and later I instantiate another object with that same line, how can I see how many milliseconds have passed? The second object may be created that same minute, over the next minutes or even hours.

11 Answers
DateTime.now.strftime("%Q")

Example usage:

>> DateTime.now.strftime("%Q")
=> "1541433332357"

>> DateTime.now.strftime("%Q").to_i
=> 1541433332357

The answer is something like:

t_start = Time.now
# time-consuming operation
t_end = Time.now

milliseconds = (t_start - t_end) * 1000.0

However, the Time.now approach risks to be inaccurate. I found this post by Luca Guidi:

https://blog.dnsimple.com/2018/03/elapsed-time-with-ruby-the-right-way/

system clock is constantly floating and it doesn't move only forwards. If your calculation of elapsed time is based on it, you're very likely to run into calculation errors or even outages.

So, it is recommended to use Process.clock_gettime instead. Something like:

def measure_time
  start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  yield
  end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
  elapsed_time = end_time - start_time
  elapsed_time.round(3)
end

Example:

elapsed = measure_time do
    # your time-consuming task here:
    sleep 2.2321
end

=> 2.232

If you want something precise, unaffected by other part of your app (Timecop) or other programs (like NTP), use Process#clock_gettime with Process::CLOCK_MONOTONIC to directly get the processor time.

t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# other code
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)

Also, if you are trying to benchmark some code tho, there is the Benchmark module for that!

require "benchmark"

time = Benchmark.realtime do
  # code to measure
end
Related