Get the most precise time in Ruby - ruby

I want to get the most possible precis time using Ruby. For example:
3.times.map do
Thread.new do
# Expect 3 differnt results from each thread
p Time.now.precis_time
end
end.each(&:join)
However, even using the strftime, I still can not achieve the goal. So is there any other way to get this?

The most precise timer available to Ruby is Process::clock_gettime. To avoid losing precision to float rounding, use :nanosecond unit:
3.times { p Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) }
# => 1491185078101717000
# => 1491185078101741000
# => 1491185078101747000
EDIT: This is the same time that is available by Time.now. On Linux, the two have nanosecond precision. However, there is another clock that has nanosecond precision even on OSX: CLOCK_MONOTONIC. This clock does not track time from epoch, but time from "some event", this event normally being your computer's boot time. To get the most precise time, one can take the difference between CLOCK_REALTIME and CLOCK_MONOTONIC and apply it later:
clock_diff = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) -
Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
3.times {
nsec = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) + clock_diff
time = Time.at(nsec / 1_000_000_000, nsec % 1_000_000_000 / 1_000.0)
p time.strftime("%Y-%m-%d %H:%i:%s.%N")
}

On Linux, I think the most precise time is just Time.now. The to_r method "is intended to be used to get an accurate value representing the nanoseconds since the Epoch" (from the docs).
t = Time.now
p t.to_r # =>(1491206113721862629/1000000000)
p [t.to_i, t.nsec] # =>[1491206113, 721862629]

On JRuby, you can use java.lang.System.nano_time :
java.lang.System.nano_time - java.lang.System.nano_time
# -15607
to get nanoseconds since a fixed but arbitrary origin. From the documentation :
This method can only be used to measure elapsed time and is not
related to any other notion of system or wall-clock time. The value
returned represents nanoseconds since some fixed but arbitrary origin
time (perhaps in the future, so values may be negative). The same
origin is used by all invocations of this method in an instance of a
Java virtual machine; other virtual machine instances are likely to
use a different origin.
If you want a precise Time with Java < 9, you could use currentTimeMillis :
java.lang.System.current_time_millis
#=> 1491214503112
But then, you wouldn't get more information than from Time.now :
Time.now.to_f
#=> 1491214592.562
So Time.now might be your best bet : it will work on any Ruby version on any system. Note that nanoseconds precision doesn't mean nanoseconds accuracy.
I dare say you could ignore any digit related to a shorter time than milliseconds. You could output the distance between NYC and Los-Angeles in micrometers, it doesn't mean it would be useful though.

Related

Get current system time in milliseconds

In Ruby, what is the right way to get the current system time since epoch(1970) in milliseconds?
I tried Time.now.to_i , it seems not the result I want. I need the result shows milliseconds and with long type, not float or double.
(Time.now.to_f * 1000).to_i
Time.now.to_f shows you the time including decimal numbers. To get number of miliseconds just multiply the time by 1000.
You can combine to_i and usec. The former returns the number of seconds since the Epoch, the latter returns the number of microseconds:
require 'time'
t = Time.at(1473152006, 2000)
t.to_i * 1000 + t.usec / 1000
#=> 1473152006002
This is equivalent to:
t.strftime('%s%L')
#=> "1473152006002"
In some cases like the above, to_f would introduce a slight floating point error:
t.to_f * 1000
#=> 1473152006001.9998
(t.to_f * 1000).to_i
#=> 1473152006001

Ruby - new_offset losing a second

I'm not sure if this behaviour is intended, but it seems a bit weird to me. I'm using the code from How do you get DateTime.parse to return a time in your time zone?
require 'date'
estHoursOffset = +10 # Brisbane/Australia
estOffset = Rational(estHoursOffset, 24)
With some times, the DateTime that's returned is a second earlier:
(DateTime.parse("2012-07-15 16:56:00") - (estHoursOffset/24.0)).new_offset(estOffset)
=> #<DateTime: 2012-07-15T16:55:59+10:00 (2456123.788888889,5/12,2299161)>
But with other times, it seems correct:
(DateTime.parse("2012-07-15 16:16:00") - (estHoursOffset/24.0)).new_offset(estOffset)
=> #<DateTime: 2012-07-15T16:16:00+10:00 (2456123.7611111114,5/12,2299161)>
The program I'm writing only cares about the minutes, which means I'm getting back 16:55 when I want 16:56.
So my questions are;
Is this intentional? (If so, is it documented somewhere - I haven't been able to find anything.)
Is there a simple way of fixing this programmatically? Since I don't care about seconds,I suppose I could "round up" the DateTimes returned, but it'd be good to know if this could bring up any other problems in edge cases.
This is probably because floating point numbers are imprecise - the 10/24.0 you are subtracting cannot be represented exactly.
If instead of subtracting that float you subtracted a rational, ie Rational(estHoursOffset, 24) then you should be ok
I tried both times ("2012-07-15 16:56:00" & "2012-07-15 16:16:00") and Ruby was always yielding the times parsed initially. I don't know mate how you managed to get 1 sec less; it is a miracle!! Only joking :)
If this still is giving you a hard time try getting the date (& time) - simpler like this..:
require 'date'
$date = Time.now #current date/time
puts $date
puts $date.min #if you want to use only the minutes
$date="2012-07-15 16:56:00" #if you want to parse it yourself
Moving on to your questions:
-No this is not international and it could be intermittent as well. I've tested your code above (+10h Australia) & from my location London, England (+1h). ALWAYS GOT the time parsed; never a second less or more.
Now if you need to round up the seconds so you will be 100% sure that each & every time you are getting the same results..:
def round_up(seconds)
divisor = 10**Math.log10(seconds).floor
i = seconds / divisor
remainder = seconds % divisor
if remainder == 0
i * divisor
else
(i + 1) * divisor
end
end
I cannot see why the rounding will cause problems in boundary conditions; as long as you always keep rounding everything! Hope this helps! Good luck mate :)

using probability for rounding decimals

What might be a simple Ruby way to round numbers using probability, i.e., based on how close the value is to one boundary or the other (floor or ceiling)?
For example, given a current price value of 28.33, I need to add 0.014.
Equivalent to starting with 28.34 and needing to add 0.004, but the final value must be rounded to two decimal places(which can be provided as parameter, or fixed for now).
The final value should therefore be:
28.34 with 60% chance, since it is that much closer, OR
28.35 with 40% random chance
The reason it occured to me this could serve best is that the application is stateless and independent across runs, but still needs to approximate the net effect of accumulating the less significant digits normally rounded into oblivion (eg. micropenny values that do have an impact over time). For example, reducing a stop-loss by some variable increment every day (subtraction like -0.014 above instead).
It would be useful to extend this method to the Float class directly.
How about:
rand(lower..upper) < current ? lower.round(2) : upper.round(2)
EDIT:
The above will only work if you use Ruby 1.9.3 (due to earlier versions not supporting rand in a range).
Else
random_number = rand * (upper-lower) + lower
random_number < current ? lower.round(2) : upper.round(2)
Wound up using this method:
class Float
def roundProb(delta, prec=2)
ivalue=self
chance = rand # range 0..1, nominally averaged at 0.5
# puts lower=((ivalue + delta)*10**prec -0.5).round/10.0**prec # aka floor
# puts upper=((ivalue + delta)*10**prec +0.5).round/10.0**prec # ceiling
ovalue=((ivalue + delta)*10**prec +chance-0.5).round/10.0**prec # proportional probability
return ovalue
rescue
puts $#, $!
end
end
28.33.roundProb(0.0533)
=> 28.39
Maybe not the most elegant approach but seems to work for the general case of any precision, default 2. Even works on Ruby 1.8.7 I'm stuck with in one case, which lacks a precision parameter to round().

How to time an operation in milliseconds in Ruby?

I'm wishing to figure out how many milliseconds a particular function uses. So I looked high and low, but could not find a way to get the time in Ruby with millisecond precision.
How do you do this? In most programming languages its just something like
start = now.milliseconds
myfunction()
end = now.milliseconds
time = end - start
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.
You can also use the built-in Benchmark.measure function:
require "benchmark"
puts(Benchmark.measure { sleep 0.5 })
Prints:
0.000000 0.000000 0.000000 ( 0.501134)
Using Time.now (which returns the wall-clock time) as base-lines has a couple of issues which can result in unexpected behavior. This is caused by the fact that the wallclock time is subject to changes like inserted leap-seconds or time slewing to adjust the local time to a reference time.
If there is e.g. a leap second inserted during measurement, it will be off by a second. Similarly, depending on local system conditions, you might have to deal with daylight-saving-times, quicker or slower running clocks, or the clock even jumping back in time, resulting in a negative duration, and many other issues.
A solution to this issue is to use a different time of clock: a monotonic clock. This type of clock has different properties than the wall clock.
It increments monitonically, i.e. never goes back and increases at a constant rate. With that, it does not represent the wall-clock (i.e. the time you read from a clock on your wall) but a timestamp you can compare with a later timestamp to get a difference.
In Ruby, you can use such a timestamp with Process.clock_gettime(Process::CLOCK_MONOTONIC) like follows:
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63988.576809828
sleep 1.5 # do some work
t2 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
# => 63990.08359163
delta = t2 - t1
# => 1.5067818019961123
delta_in_milliseconds = delta * 1000
# => 1506.7818019961123
The Process.clock_gettime method returns a timestamp as a float with fractional seconds. The actual number returned has no defined meaning (that you should rely on). However, you can be sure that the next call will return a larger number and by comparing the values, you can get the real time difference.
These attributes make the method a prime candidate for measuring time differences without seeing your program fail in the least opportune times (e.g. at midnight at New Year's Eve when there is another leap-second inserted).
The Process::CLOCK_MONOTONIC constant used here is available on all modern Linux, BSD, and macOS systems as well as the Linux Subsystem for Windows. It is however not yet available for "raw" Windows systems. There, you can use the GetTickCount64 system call instead of Process.clock_gettime which also returns a timer value in millisecond granularity on Windows (>= Windows Vista, Windows Server 2008).
With Ruby, you can call this function like this:
require 'fiddle'
# Get a reference to the function once
GetTickCount64 = Fiddle::Function.new(
Fiddle.dlopen('kernel32.dll')['GetTickCount64'],
[],
-Fiddle::TYPE_LONG_LONG # unsigned long long
)
timestamp = GetTickCount64.call / 1000.0
# => 63988.576809828
You should take a look at the benchmark module to perform benchmarks. However, as a quick and dirty timing method you can use something like this:
def time
now = Time.now.to_f
yield
endd = Time.now.to_f
endd - now
end
Note the use of Time.now.to_f, which unlike to_i, won't truncate to seconds.
Also we can create simple function to log any block of code:
def log_time
start_at = Time.now
yield if block_given?
execution_time = (Time.now - start_at).round(2)
puts "Execution time: #{execution_time}s"
end
log_time { sleep(2.545) } # Execution time: 2.55s
Use Time.now.to_f
The absolute_time gem is a drop-in replacement for Benchmark, but uses native instructions to be far more accurate.
If you use
date = Time.now.to_i
You're obtaining time in seconds, that is far from accurate, specially if you are timing little chunks of code.
The use of Time.now.to_i return the second passed from 1970/01/01. Knowing this you can do
date1 = Time.now.to_f
date2 = Time.now.to_f
diff = date2 - date1
With this you will have difference in second magnitude. If you want it in milliseconds, just add to the code
diff = diff * 1000
I've a gem which can profile your ruby method (instance or class) - https://github.com/igorkasyanchuk/benchmark_methods.
No more code like this:
t = Time.now
user.calculate_report
puts Time.now - t
Now you can do:
benchmark :calculate_report # in class
And just call your method
user.calculate_report

Fastest way to get maximum value from an exclusive Range in ruby

Ok, so say you have a really big Range in ruby. I want to find a way to get the max value in the Range.
The Range is exclusive (defined with three dots) meaning that it does not include the end object in it's results. It could be made up of Integer, String, Time, or really any object that responds to #<=> and #succ. (which are the only requirements for the start/end object in Range)
Here's an example of an exclusive range:
past = Time.local(2010, 1, 1, 0, 0, 0)
now = Time.now
range = past...now
range.include?(now) # => false
Now I know I could just do something like this to get the max value:
range.max # => returns 1 second before "now" using Enumerable#max
But this will take a non-trivial amount of time to execute. I also know that I could subtract 1 second from whatever the end object is is. However, the object may be something other than Time, and it may not even support #-. I would prefer to find an efficient general solution, but I am willing to combine special case code with a fallback to a general solution (more on that later).
As mentioned above using Range#last won't work either, because it's an exclusive range and does not include the last value in it's results.
The fastest approach I could think of was this:
max = nil
range.each { |value| max = value }
# max now contains nil if the range is empty, or the max value
This is similar to what Enumerable#max does (which Range inherits), except that it exploits the fact that each value is going to be greater than the previous, so we can skip using #<=> to compare the each value with the previous (the way Range#max does) saving a tiny bit of time.
The other approach I was thinking about was to have special case code for common ruby types like Integer, String, Time, Date, DateTime, and then use the above code as a fallback. It'd be a bit ugly, but probably much more efficient when those object types are encountered because I could use subtraction from Range#last to get the max value without any iterating.
Can anyone think of a more efficient/faster approach than this?
The simplest solution that I can think of, which will work for inclusive as well as exclusive ranges:
range.max
Some other possible solutions:
range.entries.last
range.entries[-1]
These solutions are all O(n), and will be very slow for large ranges. The problem in principle is that range values in Ruby are enumerated using the succ method iteratively on all values, starting at the beginning. The elements do not have to implement a method to return the previous value (i.e. pred).
The fastest method would be to find the predecessor of the last item (an O(1) solution):
range.exclude_end? ? range.last.pred : range.last
This works only for ranges that have elements which implement pred. Later versions of Ruby implement pred for integers. You have to add the method yourself if it does not exist (essentially equivalent to special case code you suggested, but slightly simpler to implement).
Some quick benchmarking shows that this last method is the fastest by many orders of magnitude for large ranges (in this case range = 1...1000000), because it is O(1):
user system total real
r.entries.last 11.760000 0.880000 12.640000 ( 12.963178)
r.entries[-1] 11.650000 0.800000 12.450000 ( 12.627440)
last = nil; r.each { |v| last = v } 20.750000 0.020000 20.770000 ( 20.910416)
r.max 17.590000 0.010000 17.600000 ( 17.633006)
r.exclude_end? ? r.last.pred : r.last 0.000000 0.000000 0.000000 ( 0.000062)
Benchmark code is here.
In the comments it is suggested to use range.last - (range.exclude_end? ? 1 : 0). It does work for dates without additional methods, but will never work for non-numeric ranges. String#- does not exist and makes no sense with integer arguments. String#pred, however, can be implented.
I'm not sure about the speed (and initial tests don't seem incredibly fast), but the following might do what you need:
past = Time.local(2010, 1, 1, 0, 0, 0)
now = Time.now
range = past...now
range.to_a[-1]
Very basic testing (counting in my head) showed that it took about 4 seconds while the method you provided took about 5-6. Hope this helps.
Edit 1: Removed second solution as it was totally wrong.
I can't think there's any way to achieve this that doesn't involve enumerating the range, at least unless as already mentioned, you have other information about how the range will be constructed and therefore can infer the desired value without enumeration. Of all the suggestions, I'd go with #max, since it seems to be most expressive.
require 'benchmark'
N = 20
Benchmark.bm(30) do |r|
past, now = Time.local(2010, 2, 1, 0, 0, 0), Time.now
#range = past...now
r.report("range.max") do
N.times { last_in_range = #range.max }
end
r.report("explicit enumeration") do
N.times { #range.each { |value| last_in_range = value } }
end
r.report("range.entries.last") do
N.times { last_in_range = #range.entries.last }
end
r.report("range.to_a[-1]") do
N.times { last_in_range = #range.to_a[-1] }
end
end
user system total real
range.max 49.406000 1.515000 50.921000 ( 50.985000)
explicit enumeration 52.250000 1.719000 53.969000 ( 54.156000)
range.entries.last 53.422000 4.844000 58.266000 ( 58.390000)
range.to_a[-1] 49.187000 5.234000 54.421000 ( 54.500000)
I notice that the 3rd and 4th option have significantly increased system time. I expect that's related to the explicit creation of an array, which seems like a good reason to avoid them, even if they're not obviously more expensive in elapsed time.

Resources