-
-
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
Measure time with monotonic clock #5107
Conversation
Introduces a Time::Measure struct that records a monotonic clock after which we can compute how much time has elpased since it was recorded, unaffected by time fluctuations such as leap-seconds or manually changing the computer time.
I just learnt it using Crystal, so Crystal made me more educated 👨🎓 |
Could we just get a Time.monotonic returning a Time::Span or even a Float64 of seconds? ...Because I think that there are many more legitimate use cases for globally monotonic time than just measuring the time difference. Besides, we already have many benchmarking tools. |
But if you do still want to go for this kind of API, please add an atomic restart feature, to avoid another bad practice. |
I just gave this more thought and realized that the use case of an absolute time reference is not covered either. For example, I might want to store the creation time for each of my objects and then order them by it. There's simply no way to do this with this kind of API even if I stored this object because it produces a different value every time its method is called. The underlying implementation is fine and there's no reason whatsoever to hide that absolute number. Just make a method returning a People are indeed very happy to use the subtraction idiom. It's not only popular but also very intuitive. Just explain that they want to use it on something other than All in all, I cannot support an API that adds a new type and 8 new methods but covers only a small fraction of use cases that one simple and familiar method can cover. So, 👎 from me. |
Since monotonic clocks only mean something when compared, I only look for measuring time here —the obvious use case. Do you have other use cases that involve using raw monotonic clocks (e.g. as a float)? I guess a Maybe there could be a clock = Time.start
clock.elapsed
clock.restart
clock.elapsed?(5.seconds) |
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it's better to use if
instead of once
. It feels to me like it might suggest this could be blocking until that amount of time has passed.
Maybe just @oprypin The problem with reusing an existing concept like |
@straight-shoota, I have nothing to add, because my comment already addresses all you said. |
|
||
5.times do | ||
elapsed = timer.elapsed | ||
elapsed.should be >= previous |
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.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion:
Time measurement relies on a monotonic clock that is strictly linearly increasing.
This clock should be independent from time fluctuations, such as leap seconds, time zone adjustments or manual changes to the computer's wall time.
Except there's little we as language authors can do to solve these, apart from provide easy to use classes, and document that they should be used for passwords. This is an opportunity where we can do something, and so I think we should do it. |
And no, go has the exact same backwards compatiability constrains we have here (none for adding an API). They could have introduced a new monotonic time API just like this PR does, and that wouldn't have "broken backwards compatability". We too have plenty of shards which use These kind of time bugs are special, because they only really happen on leap seconds, which occur very rarely. So it's unlikely that bugs will be found until they're run in production unless he application is fuzzed for time shifts which is very unlikely and unweildy. |
@oprypin I missed your previous comment, and ... I believe you're totally right; there can be use cases to get the monotonic clock and not necessarily measure elapsed time. The go-like alternative of mixing a monotonic and realtime clocks in a single What about simply having It would be simple enough, doesn't create new types, and would be future-proof to whether we merge realtime+monotonic clocks in |
Well I also have said basically that so I definitely agree |
I must say, I was actually surprised to see |
Introduces a
Time::Measure
struct andTime.measure { do_something }
API (as proposed in #4556 (comment)) for measuring time using a monotonic clock, unaffected by time fluctuations such as leap seconds or manually changing the computer time.This doesn't modify the
Time
struct: no doubleclock_gettime
syscalls (orgettimeofday
+mach_absolute_time
syscalls on macOS); no bloat ofTime
withseconds
in both realtime and monotonic clocks, or requiringTime#-
to deal with the absense of monotonic seconds (e.g.Time.new(2016, 1, 1)
); ...This assumes developers can be educated to use better API instead of relying on the dumb, bad and broken
Time.now - Time.now
, just like we assume that developers can be educated to use bcrypt or argon2i to hash passwords, or useRandom::Secure
to generate tokens.Examples:
Supersedes #3827.