How do I get elapsed time in milliseconds in Ruby?
RubyRuby Problem Overview
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.
Ruby Solutions
Solution 1 - Ruby
As stated already, you can operate on Time
objects as if they were numeric (or floating point) values. These operations result in second resolution which can easily be converted.
For example:
def time_diff_milli(start, finish)
(finish - start) * 1000.0
end
t1 = Time.now
# arbitrary elapsed time
t2 = Time.now
msecs = time_diff_milli t1, t2
You will need to decide whether to truncate that or not.
Solution 2 - Ruby
You can add a little syntax sugar to the above solution with the following:
class Time
def to_ms
(self.to_f * 1000.0).to_i
end
end
start_time = Time.now
sleep(3)
end_time = Time.now
elapsed_time = end_time.to_ms - start_time.to_ms # => 3004
Solution 3 - Ruby
I think the answer is incorrectly chosen, that method gives seconds, not milliseconds.
t = Time.now.to_f
=> 1382471965.146
Here I suppose the floating value are the milliseconds
Solution 4 - Ruby
DateTime.now.strftime("%Q")
Example usage:
>> DateTime.now.strftime("%Q")
=> "1541433332357"
>> DateTime.now.strftime("%Q").to_i
=> 1541433332357
Solution 5 - Ruby
To get time in milliseconds, it's better to add .round(3)
, so it will be more accurate in some cases:
puts Time.now.to_f # => 1453402722.577573
(Time.now.to_f.round(3)*1000).to_i # => 1453402722578
Solution 6 - Ruby
ezpz's answer is almost perfect, but I hope I can add a little more.
Geo asked about time in milliseconds; this sounds like an integer quantity, and I wouldn't take the detour through floating-point land. Thus my approach would be:
t8 = Time.now
# => Sun Nov 01 15:18:04 +0100 2009
t9 = Time.now
# => Sun Nov 01 15:18:18 +0100 2009
dif = t9 - t8
# => 13.940166
(1000 * dif).to_i
# => 13940
Multiplying by an integer 1000 preserves the fractional number perfectly and may be a little faster too.
If you're dealing with dates and times, you may need to use the DateTime class. This works similarly but the conversion factor is 24 * 3600 * 1000 = 86400000 .
I've found DateTime's strptime and strftime functions invaluable in parsing and formatting date/time strings (e.g. to/from logs). What comes in handy to know is:
-
The formatting characters for these functions (%H, %M, %S, ...) are almost the same as for the C functions found on any Unix/Linux system; and
-
There are a few more: In particular, %L does milliseconds!
Solution 7 - Ruby
%L
gives milliseconds in ruby
require 'time'
puts Time.now.strftime("%Y-%m-%dT%H:%M:%S.%L")
or
puts Time.now.strftime("%Y-%m-%d %H:%M:%S.%L")
will give you current timestamp in milliseconds.
Solution 8 - Ruby
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
Solution 9 - Ruby
Time.now.to_f can help you but it returns seconds.
In general, when working with benchmarks I:
- put in variable the current time;
- insert the block to test;
- put in a variable the current time, subtracting the preceding current-time value;
It's a very simple process, so I'm not sure you were really asking this...
Solution 10 - Ruby
Try subtracting the first Time.now from the second. Like so:
a = Time.now
sleep(3)
puts Time.now - a # about 3.0
This gives you a floating-point number of the seconds between the two times (and with that, the milliseconds).
Solution 11 - Ruby
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