I want to perform an action at a regular interval in my multi-threaded Python application. I have seen two different ways of doing it
exit = False
def thread_func():
while not exit:
action()
time.sleep(DELAY)
or
exit_flag = threading.Event()
def thread_func():
while not exit_flag.wait(timeout=DELAY):
action()
Is there an advantage to one way over the other? Does one use less resources, or play nicer with other threads and the GIL? Which one makes the remaining threads in my app more responsive?
(Assume some external event sets exit
or exit_flag
, and I am willing to wait the full delay while shutting down)
Best Answer
Using
exit_flag.wait(timeout=DELAY)
will be more responsive, because you'll break out of the while loop instantly whenexit_flag
is set. Withtime.sleep
, even after the event is set, you're going to wait around in thetime.sleep
call until you've slept forDELAY
seconds.In terms of implementation, Python 2.x and Python 3.x have very different behavior. In Python 2.x
Event.wait
is implemented in pure Python using a bunch of smalltime.sleep
calls:This actually means using
wait
is probably a bit more CPU-hungry than just sleeping the fullDELAY
unconditionally, but has the benefit being (potentially a lot, depending on how longDELAY
is) more responsive. It also means that the GIL needs to be frequently re-acquired, so that the next sleep can be scheduled, whiletime.sleep
can release the GIL for the fullDELAY
. Now, will acquiring the GIL more frequently have a noticeable effect on other threads in your application? Maybe or maybe not. It depends on how many other threads are running and what kind of work loads they have. My guess is it won't be particularly noticeable unless you have a high number of threads, or perhaps another thread doing lots of CPU-bound work, but its easy enough to try it both ways and see.In Python 3.x, much of the implementation is moved to pure C code:
And the C code that acquires the lock:
This implementation is responsive, and doesn't require frequent wakeups that re-acquire the GIL, so you get the best of both worlds.