Title: Condition.wait timeout can't be set to more than 50 ms
Type: Stage: resolved
Components: Library (Lib) Versions: Python 2.7
Status: closed Resolution: wont fix
Dependencies: Superseder:
Assigned To: Nosy List: Bill.Sobel, bkabrda, pitrou, yarda
Priority: normal Keywords:

Created on 2013-04-16 09:22 by bkabrda, last changed 2013-10-09 21:58 by Bill.Sobel. This issue is now closed.

Messages (4)
msg187060 - (view) Author: Bohuslav "Slavek" Kabrda (bkabrda) * Date: 2013-04-16 09:22
On Python 2, Condition.wait timeout is always taken as

min(delay * 2, remaining, .05)

which means it cannot be longer than 50 ms. I don't see a reason for this and AFAIK this is no longer true for Python 3, where timeout can be arbitrarily long. Would it be possible to replace the min() call with just "remaining" completely? If not, would it at least be possible to add an argument to wait(), that would trigger this behaviour (something like patch suggested by Jaroslav Skarvada [1] who reported this issue at [2])?


msg187062 - (view) Author: Jaroslav Škarvada (yarda) Date: 2013-04-16 09:35
The current behaviour is not good for power consumption especially with the current tickless kernels - the python processes using "threading" shows in the top of the "powertop" list (on machine tuned for low power consumption) causing 20 wakeups per second.

Also I can confirm the python3 behaves correctly (shows in the bottom of the "powertop" list).
msg187063 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-04-16 09:45
Locks in 2.7 don't support a timeout, which is why Condition.wait has a polling loop. The comment explains it all:

 # Balancing act:  We can't afford a pure busy loop, so we
 # have to sleep; but if we sleep the whole timeout time,
 # we'll be unresponsive. 

Lock timeouts are a new feature in 3.2 and therefore won't be backported in 2.7, which is in bugfix mode. Consider it a good reason to switch to 3.x :-)

(yes, we are aware about the power consumption issue)
msg199351 - (view) Author: Bill Sobel (Bill.Sobel) Date: 2013-10-09 21:58
I'd like to suggest a easy fix here (I saw this was closed, but the posters were asking for a behavior change).  With this fix there is no behavior change to callers or new parameters to the API.

if remaining >= 4.0:
    maxDelay = 1
    maxDelay = .05
delay = min(delay * 2, remaining, maxDelay)

With this fix the loop waits 1 second until it is 'close' to the expiration time then goes into its normal 20 times per-second check.  For long waits this is what is causing the power issue and is alleviated by throttling back on the check when not close to expiration.
Date User Action Args
2013-10-09 21:58:48Bill.Sobelsetnosy: + Bill.Sobel
messages: + msg199351
2013-04-16 09:45:02pitrousetstatus: open -> closed

nosy: + pitrou
messages: + msg187063

resolution: wont fix
stage: resolved
2013-04-16 09:35:13yardasetnosy: + yarda
messages: + msg187062
2013-04-16 09:22:52bkabrdacreate