[Python-ideas] time.Timer
anatoly techtonik
techtonik at gmail.com
Wed Feb 26 18:37:12 CET 2014
On Wed, Feb 26, 2014 at 11:29 AM, Chris Angelico <rosuav at gmail.com> wrote:
> On Wed, Feb 26, 2014 at 4:24 PM, anatoly techtonik <techtonik at gmail.com> wrote:
>> UX improvement fix for the common case:
>>
>> import time
>>
>> class Timer(object):
>> def __init__(self, seconds):
>> self.seconds = seconds
>> self.restart()
>>
>> def restart(self):
>> self.end = time.time() + self.seconds
>>
>> @property
>> def expired(self):
>> return (time.time() > self.end)
>
> You just showed how easy it is to implement it manually :)
Yes, but the frequency of this element made it a better position than
other datetime functions.
> Your example, though, is a really bad idea:
>
>> class FPS(object):
>> def __init__(self):
>> self.counter = 0
>> self.timer = Timer(1)
>> def process(self):
>> self.counter += 1
>> if self.timer.expired:
>> print "FPS: %s" % self.counter
>> self.counter = 0
>> self.timer.restart()
>
> Implication is that you call process() many times a second, right?
> Well, querying the current system time is often quite expensive, so
> this could seriously damage your FPS; and more importantly, it's
> inaccurate. Let's suppose you're actually achieving 2.5 FPS - that is
> to say, you call process() every 400ms. Here's how it'll go:
>
> Time 400: not expired
> Time 800: not expired
> Time 1200: expired, reset time to zero
> Time 1600: timer says 400, not expired
> Time 2000: timer says 800, not expired
> Time 2400: timer says 1200, expired, reset time to zero
>
> You're going to say 3 FPS, when it's really 2.5.
+/- 1 FPS is acceptable error as long as FPS doesn't fall below 60.
For my script that in PySDL2 is about 1000 for filling a small window
with lines.
> For measuring FPS,
> you should probably use an algorithm more like this:
>
> 1) Spawn an FPS counter thread, or async alarm, or something, to be
> executed every second.
I don't want to mess with woes of concurrent programming
for this kind of accuracy. Python is good at what it is good for.
https://stackoverflow.com/questions/134867/which-programming-language-makes-concurrent-programming-as-easy-as-possible
> 2) Each frame, increment a counter. Never reset the counter.
Although offtopic, but I don't get why resetting a counter is worse
than storing two values and subtracting them.
> 3) Every time the alarm goes off, record the current time and the
> current frame counter.
> 4) Your FPS is (frames - last_frames) / (time - last_time)
>
> That way, you query the current time roughly once a second. It's safe
> against sleep(1) taking more than one second to return (because it
> actually queries the time), it's safe against the FPS being extremely
> low, and it's fairly efficient.
It increases complexity, but doesn't increase accuracy, and therefore
is fairly inefficient for maintenance. In formula:
(frames - last_frames) / (time - last_time)
(time - last_time) == 1
so where I get 3 frames, your code will get 2. The code only makes
sense when timer fire is delayed (I don't know if it is the case with
threads) or when you make frame-based FPS measurements (every
10 frames or so).
> Plus, it doesn't require any code in the time module :)
FPS is only one problem that timer solves.
https://www.google.by/search?q=timer - even Google calculator has one.
More information about the Python-ideas
mailing list