-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Measure time with monotonic clock #5107
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
require "spec" | ||
|
||
describe Time::Measure do | ||
it "Time.measure" do | ||
elapsed = Time.measure { sleep 0.001 } | ||
elapsed.should be >= 1.millisecond | ||
end | ||
|
||
it "returns elapsed time" do | ||
timer = Time::Measure.new | ||
previous = timer.elapsed | ||
|
||
5.times do | ||
elapsed = timer.elapsed | ||
elapsed.should be >= previous | ||
end | ||
end | ||
|
||
it "elapsed?" do | ||
timer = Time::Measure.new | ||
|
||
# disabled: randomly fails | ||
# timer.elapsed?(0.seconds).should be_true | ||
|
||
timer.elapsed?(5.seconds).should be_false | ||
timer.elapsed?(5.0).should be_false | ||
sleep 0.001 | ||
timer.elapsed?(0.001).should be_true | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
lib LibC | ||
struct MachTimebaseInfo | ||
numer : UInt32 | ||
denom : UInt32 | ||
end | ||
|
||
fun mach_timebase_info(info : MachTimebaseInfo*) : LibC::Int | ||
fun mach_absolute_time : UInt64 | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
require "crystal/system/time" | ||
|
||
struct Time | ||
# Measure elapsed time. | ||
# | ||
# Time measurement relies on a monotonic clock, that should be independent to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion:
|
||
# time fluctuations, such as leap seconds or manually changing the computer | ||
# time. | ||
struct Measure | ||
private getter seconds : Int64 | ||
private getter nanoseconds : Int32 | ||
|
||
# Starts a clock to measure elapsed time, or repeatedly report elapsed time | ||
# since an initial start time. | ||
def initialize | ||
@seconds, @nanoseconds = Crystal::System::Time.monotonic | ||
end | ||
|
||
# Returns the time span since the clock was started. | ||
# | ||
# ``` | ||
# timer = Time::Measure.new | ||
# | ||
# loop do | ||
# do_something | ||
# p timer.elapsed # => 00:00:01.000000023 | ||
# end | ||
# ``` | ||
def elapsed | ||
seconds, nanoseconds = Crystal::System::Time.monotonic | ||
Time::Span.new(seconds: seconds - @seconds, nanoseconds: nanoseconds - @nanoseconds) | ||
end | ||
|
||
# Returns true once *span* time has passed since the clock was created. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe it's better to use |
||
# | ||
# ``` | ||
# timeout = 5.seconds | ||
# timer = Time::Measure.new | ||
# | ||
# until timer.elapsed?(timeout) | ||
# do_domething | ||
# end | ||
# ``` | ||
def elapsed?(span : Time::Span) | ||
elapsed >= span | ||
end | ||
|
||
# Returns true once *span* seconds have passed since the clock was created. | ||
# | ||
# ``` | ||
# timer = Time::Measure.new | ||
# | ||
# until timer.elapsed?(5.0) | ||
# do_domething | ||
# end | ||
# ``` | ||
def elapsed?(span : Int | Float) | ||
elapsed?(span.seconds) | ||
end | ||
end | ||
|
||
# Measures how long the block took to run. | ||
# | ||
# ``` | ||
# elapsed = Time.measure { do_something } # => 00:01:53.009871361 | ||
# ``` | ||
def self.measure(&block) : Time::Span | ||
clock = Measure.new | ||
yield | ||
clock.elapsed | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add
previous = elapsed
after this line to ensure it is monotonic? Currently, the 3rd measurement might be smaller than the second.