How to Time an Operation in Milliseconds in Ruby

How to time an operation in milliseconds in Ruby?

You can use ruby's Time class. For example:

t1 = Time.now
# processing...
t2 = Time.now
delta = t2 - t1 # in seconds

Now, delta is a float object and you can get as fine grain a result as the class will provide.

How do I get elapsed time in milliseconds in 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.

How do I display duration in milliseconds as a properly formatted string?

def time_as_str(ms)
secs, ms = ms.divmod(1000)
mins, secs = secs.divmod(60)
hours, mins = mins.divmod(60)
s = "%d.%d.%d.%s" % [hours, mins, secs, ms.zero? ? "0" : ms.to_s.sub(/0*\z/,'')]
if hours > 0
s
elsif mins > 0
s[2..-1]
else
s[4..-1]
end
end

time_as_str(86_400_000) #=> "24.0.0.0"
time_as_str(0) #=> "0.0"
time_as_str(499) #=> "0.499"
time_as_str(60_280) #=> "1.0.28"
time_as_str(360_000) #=> "6.0.0"
time_as_str(1_000_000_200) #=> "277.46.40.2"

See Integer#divmod, an oft-overlooked method.

Suppose

ms = 2_045_670

then

secs, ms    =   ms.divmod(1000)
#=> [2045, 670] (secs #=> 2045, ms #=> 670)
mins, secs = secs.divmod(60)
#=> [34, 5]
hours, mins = mins.divmod(60)
#=> [0, 34]
ms = ms.zero? ? "0" : ms.to_s.sub(/0*\z/,'')
#=> "67" (truncate)
s = "%d.%d.%d.%s" % [hours, mins, secs, ms]
#=> "0.34.5.67"
if hours > 0 # false
"0.34.5.67"
elsif mins > 0 # true
"34.5.67"
else # not evaluated
"5.67"
end
#=> "34.5.67"

Millisecond resolution of DateTime in Ruby

Changing m.happened_at = '2012-01-01T00:00:00.32323'.to_datetime in the code above to m.happened_at = '2012-01-01T00:00:00.32323' solves the problem, though I have no idea why.

In Rails, how do I output my date as a time in milliseconds in my CSV file?

You can simply call .to_i on a DateTime object:

timestamp = DateTime.now.to_i
# => 1501617998
DateTime.strptime(timestamp.to_s, '%s')
# => Tue, 01 Aug 2017 20:07:10 +0000

The timestamp is the seconds since Epoch. Multiply it by a thousand and you get milliseconds.

In your case, you must make a hook for this case:

attr_values = attributes.map do |attr| 
attr_value = value.send(attr)
attr_value = attr_value.to_i * 1000 if attr_value.is_a?(DateTime)
attr_value
end
csv << attr_values

This means everytime an attribute returns a DateTime object, it will be converted to a timestamp * 1000. If you want to filter only few attrs to convert DateTime -> Timestamp, test the attr with a whitelist instead of testing attr_value's class.

Ruby timeout a block of code after n *milli* seconds

Just use a decimal value for the timeout. Example for n milliseconds:

Timeout::timeout(n / 1000.0) { sleep(100) }

Accuracy of nanosecond component in Ruby Time

I strongly suspect this is due to Time.at taking a binary floating point number - that it has nothing to do with time at all.

I'm not a Ruby dev, but in IEEE-754 64-bit floating point types, the closest value to 421.854 is exactly

421.85399999999998499333742074668407440185546875

... so my guess is that that exact value is being truncated, effectively.

(The nearest 32-bit floating point value is 421.85400390625.)

If you use a Rational instead to specify it as effectively an integer number of milliseconds (Rational(421854, 1000)), you may well find that works. Alternatively, use at(seconds, microseconds_with_frac):

Time.at(421, 854000).utc.strftime('%M:%S.%L')

Ruby sleep or delay less than a second?

sleep(1.0/24.0)

As to your follow up question if that's the best way: No, you could get not-so-smooth framerates because the rendering of each frame might not take the same amount of time.

You could try one of these solutions:

  • Use a timer which fires 24 times a second with the drawing code.
  • Create as many frames as possible, create the motion based on the time passed, not per frame.


Related Topics



Leave a reply



Submit