-
-
Notifications
You must be signed in to change notification settings - Fork 348
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
MockClock rate=1.0 #394
Comments
Heh, basically the reason the default is Can you say more about how and why you want to use a |
Apologies -- maybe I should be a bit more precise and say begin As-is in your implementation with In my variant, I've also allowed my user to define a "start" to their clock, thus pulling back or pushing forward the virtual base attribute. In your case, it might not make any sense at all for |
Ah, I see! You're talking about wall clock / absolute time, like "January 7, 2018, 17:48:12.5839". All of Trio's time-keeping functionality is (currently) about monotonic / relative time. These are very similar and easily confused, but actually pretty different when you look at them carefully. Wall clock time is matched to the calendar, so it makes sense to say things like "what's today's date", "what's the current day of the week", etc.; you have to think about complications like DST and leap seconds; and it's possible for a computer to be confused about the current wall clock time so you have to be prepared for the time to be set, sometimes to a time in the past. In Python you normally get this from Monotonic time is simpler in most ways: it doesn't care about absolute time ("January 7 at 17:39:32"), it only cares about relative time ("this event was 1837.32491 seconds after that one"). So it doesn't try to keep track of its relationship to any absolute epoch – the actual values are arbitrary, the only guarantee is that if you check the time twice and then subtract those values, that difference tells you how many seconds have passed. Since it doesn't have to care about keeping in sync with the earth's rotation, it doesn't have to support stepping backwards, and it can guarantee that it increases by N every N seconds. (POSIX time can't make this guarantee even if we ignore clock setting, because it goes backwards during leap seconds!) Hence the name "monotonic" time. OTOH, in standard operating system implementations of monotonic time, the clock does stop while the computer is suspended, which is totally different from absolute time. In Python you normally get this from There are even other more complicated options too – according to Since There is an issue option for possibly adding wall clock / absolute time support to Trio: #173. (It might be better as a library than as part of the Trio core.) I haven't thought too much about the details of how that API might look, but definitely you'd want to have some kind of testing capability, and definitely you'd want to be able to set it to arbitrary times, advance by arbitrary amounts, etc. Do you think it's really the ability to control the speed of the clock that you want, or mainly just absolute clock support? For example, if I had set up a job to run "every Saturday at midnight", I might write a test like:
But that doesn't involve ever running the clock at any multiple of real time, just manually stepping it. Do you have an example in mind where running it normally is useful? |
Yeah, totally! This is how I originally implemented it as well.
If I had to pick, mainly absolute clock support. Controlling the speed of the clock would be a nice side-effect of this, as it's easier, as a human, to think of time passing "in seconds". I'm not sure how you could increase the speed of the clock - but I have not poured over the source code enough yet to determine how the clock advances. I've just been playing around with a custom implementation that would allow me to do what I'm looking for.
A large part of my platform will involve scheduled callbacks, sometimes days/weeks in the future. As absolute time will be a large component of this, I have already modified your I don't believe I'm asking for anything from the project quite yet as I believe my use case can be handled by a custom implementation of the Clock!
The main benefit of setting it as |
Setting My suggestion would be: in normal use, use a wall clock, like Then, for testing, you can swap in a fake version of your clock, and you make the fake clock track an offset between what the Trio monotonic clock says, and whatever fake wall time you want to pretend it is. So if you say "okay fake clock, it's currently 2018-01-07 23:37:10.1349Z", then it converts that to a POSIX time, calls And you'd probably also want some other tools in your fake clock (or in a second fake clock implementation) for simulating stuff like DST transitions and leap seconds and NTP time updates. |
Either we are disconnected, or I am misunderstanding you. This is where I left off in my code, it's fancy .. because I am terrible with names. If you run... from Clock import FancyClock
import trio
async def main():
import time
r_start = time.monotonic()
v_start = clock.now
for _ in range(9):
print(f'real: {dt.now()} ... virtual: {clock.now}')
await trio.sleep(1)
print(f'real elapsed: {time.monotonic() - r_start} seconds')
print(f'virt elapsed: {clock.now - v_start}')
if (__name__ == '__main__'):
clock = FancyClock(rate=3)
trio.run(main, clock=clock) You'll get that the virtual clock has moved forward 9 seconds, to the 3 seconds of real time that has passed. Quite literally all I've changed so far in I will say that if you chose to support a timezone-based Clock implementation, I don't know how comfortable you are requiring your users to rely on another library. For my purposes, this works very nicely and so far, my dependencies are limited to |
You're probably just as smart as them, but haven't studied as many bizarre and arcane details about computerized timekeeping. Which is probably a smart move on your part, because computerizing timekeeping has a ton of bizarre and arcane details. But... in that case, please trust me when I say, I do know a lot of bizarre and arcane details about computerized timekeeping, and what I'm trying to tell you is that the code you posted is fundamentally broken and this approach cannot work correctly. Any That doesn't mean you can't make this work, it just means that implementing a You might also find this article interesting: http://devetc.org/code/2014/01/21/timers-clocks-and-cocoa.html#fnref:unix-realtime |
I don't see an action item on this that's not covered by #173 so I'm closing it - feel free to reopen if I missed something. |
trio/trio/testing/_mock_clock.py
Line 90 in 1075239
Hi!
I've just found your project and am loving it so far. I am building an automation platform and had implemented this sort of
MockClock
synchronously, so I love what you've done here!Would recommend you use an initial rate of
1.0
, as it then implements a sort of "time travel" feature. Unless of course, you're intentionally wanting to keep the virtual time as dissimilar to real-time as possible. This is super cool and I've heavily based my clock off of yourMockClock
.This is more of a non-issue as it's about a custom implementation of the clock, but wanted to bring it up and show you another possible use case for Clocks!
Thanks for the cool work, I'm excited to keep exploring.
- SN
The text was updated successfully, but these errors were encountered: