-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
time.sleep waits less than expected #9693
Comments
You should try that on CircuitPython 9.1 or better. |
Similar in 9.1.4. A sliver of the loss (<8us) is from the time it takes to call
But the point remains that Similar results on Pico [W]:
|
Re @todbot, if you followed the linked forum discussion you'll see that bug was reproduced on 9.1.1 as well |
Right, thanks I see that now. Also, thanks @anecdata. In my experience trying to do tight-timing on CircuitPython this isn't very surprising. CircuitPython has no concept of atomic or critical sections so who knows what happens during those three function calls: USB handling and garbage collection come to mind as tasks that eat up several milliseconds. Perhaps a similar test that was disconnected from USB, does a |
What I think is odd here is that the time is less that the requested time. I'd expect overhead to make it longer. So I'm suspecting a ticks-vs-msec issue: a tick is 1/1024 of a second vs the msec 1/1000 of a second. It could be an error in converting ticks to msecs or assuming one is the other. |
Oh yes, under the requested value. You are correct. I need more coffee. |
I think adafruit_support_bill got it right way back in August: here. Plus, any short sleep will be accentuated by the floored division |
Ah yes, I have experienced this. In #9237 I was convinced it was a problem with floats in CircuitPython because 0.004 seconds * 1000 millis/sec != 4 milliseconds. |
My favorite quote from the discussion:
|
I think this is still something to follow up on. We might round instead of truncating. And I am still suspicious of 1024 vs 1000. 9.7 vs 10 is not a few least-significant bits of difference. |
I had played around with altering the value given time.sleep; the handful of substitute values tried were enough to suggest that expressions are perhaps being evaluated according to The Price is Right rules, which is to say what it returns is as near as possible the specified value without going over, within the limits of floating point/ (1000/1024) math. Using values for sleep from 0.08 to 0.011 returned results which were either 986x(- up to 90) or 1076x(- up to 20). Using 0.1 (and adjusting divisor to 10000) returned 9985(- up to 20). (These tests were done on a Metro RP2040 running 9.2.0-beta.0) |
|
Does this mean it's literally losing track of time? (fwiw: Revisiting this thread led me to imagine potential build flags for fuzzy logic. I'm too new to the project to know, but I have to think it's been discussed somewhere) |
I only see the delay being converted from ms to ticks. The rest is all done in ticks. circuitpython/supervisor/shared/tick.c Line 102 in 25216c8
The issue is not with floats, it's because the actual sleep time is in milliseconds, and there's 1024 ticks in 1000 milliseconds, so it just can't be accurate.
So that explains why it's lower than 10, but note that the function reads The only way to have a higher precision would be to use subticks (which are a 1/32th of a tick or ~31us) for sleeps below say... 1s. |
@Neradoc Right. I'd mis-read the code. It does boil down to a question of precision as you describe. |
Using subticks to increase timer resolution by 5 bits, results running on a Raspberry Pi Pico W are:
Repeating the test several times gives similar results:
I'll be making similar updates to other ports and will PR shortly. |
Maybe we could have a note in the sleep() docs about precision being limited around the millisecond. Note that C python sleep docs says:
For CP, do we guarantee it's at least the time given (by rounding up) ? Do we say it's a "closest" effort plus overhead ? Do we just say it's an approximation ? Do we note that we can't promise precise timings in CP anyway ? |
No guarantees as to whether it's a ceiling rather than a floor, because there are things that can make the interval longer, like gc and interrupt handling. Right now |
The conversion code in
My update does not support sleep timer resolution beyond integral milliseconds. Since the underlying timer has subtick resolution (in most cases), it is possible to resolve sleep to ~30 us. Perhaps change |
Are you saying change that call? One issue is if a very long sleep would overflow the 32-bit arg to |
Because there is not a generic |
CircuitPython version
Code/REPL
Behavior
The result shows:
expected 10000 us, got 9799.07 us
Description
see:
https://forums.adafruit.com/viewtopic.php?p=1024856#p1024856
Additional information
No response
The text was updated successfully, but these errors were encountered: