[Python-ideas] time.Timer

Chris Angelico rosuav at gmail.com
Wed Feb 26 09:29:51 CET 2014


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 :)

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. 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.
2) Each frame, increment a counter. Never reset the counter.
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.

Plus, it doesn't require any code in the time module :)

ChrisA


More information about the Python-ideas mailing list