classification
Title: No sleep or busy wait
Type: enhancement Stage: test needed
Components: Tkinter Versions: Python 2.7
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: ajaksu2, gpolo, jbrouwers, loewis
Priority: normal Keywords:

Created on 2003-07-31 00:14 by jbrouwers, last changed 2009-04-22 22:09 by gpolo. This issue is now closed.

Messages (5)
msg61117 - (view) Author: Jean M. Brouwers (jbrouwers) Date: 2003-07-31 00:14
This is a request for three, related changes to file
Modules/_tkinter.c in Python 2.3, specifically to avoid
sleeping or busy waiting.


1) The main loop, function Tkapp_Mainloop(), includes a
now configurable sleep period which may cause
undesirable delays (in the threaded builds).  If no
Tcl/Tk event was handled, the main loop sleeps for 20
millisec (or whatever the value of
Tkinter_busywaitinterval* is).

Another, better way to achieve that would be to create
a timer event for in the main loop BEFORE calling the
Tcl/Tk event handler and call the Tcl/Tk event handler
with a zero argument to wait for an event**.

This produces the same idle period as the current
implementation.  The difference is that the main loop
(actually the Tcl/Tk event handler) stays awake instead
of going to sleep for the idle period.  Any events
occurring during the idle period will be handled
without delay.


2) In addition, only one event is handled per iteration
of the main loop, causing the state to be saved and
restored, locks to be acquired and releases, etc. many
times.

Instead handle not one event, but all pending events. 
After handling one event, all other pending events
should be handled as well by calling the Tcl/Tk event
handler again (with a TCL_DONT_WAIT argument) until
there are no more events.

The net result is that any pending events are handled
more quickly and with less overhead.


3) After the first change abiove, static function
Sleep() can be removed.  It is still needed in function
WaitForMainloop() but that call can be replaced by
Tcl_Sleep().  Tcl_Sleep() is equivalent to Sleep() and
it works on all platforms, not just those which have
select().

--------
*) The name Tkinter_busywaitinterval is a misnomer.  It
is not a busy wait but a non-buzy sleep, at least with
Tcl_Sleep().

**) There are a few more details to make this work
correctly and I have a version for _tkinter.c which
does implement these changes.
msg61118 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2003-09-07 19:37
Logged In: YES 
user_id=21627

1) The main-loop is inherently *busy*-wait, as the loop is
continuously polling for events. The interval between two of
these wait-for-event calls is then indeed a busywaitinterval.

2) Processing all events would mean that other threads
cannot invoke Tcl methods while there are pending requests.
This would be a change in behaviour, and might influence
responsiveness in a undesirable way.

3) Can you name a platform on which the current Sleep does
not work?
msg61119 - (view) Author: Jean M. Brouwers (jbrouwers) Date: 2003-09-07 22:48
Logged In: YES 
user_id=832557

No, I do not know of any platforms where the current Sleep()
implementation in Tkinter would not work.  That aside, I
believe that there are still two issues with using Sleep().

From previous experience with Tcl/Tk (non-Python), I do know
that events tend to pile up in single-threaded, event driven
applications which use Tcl timer events.  In such
applications calls like Sleep() or Tcl_Sleep() should be
avoided entirely.  Using Tcl/Tk timer events is a far better
approach in this case, for reasons mentioned earlier.

I'm not familiar enough with Tkinter, multi-threading and
the impact of Sleep() in Python.  However, instead of using
Sleep(), what about yield() or some similar threading
function?  And compile that call only in the threaded Python
build?
msg81856 - (view) Author: Daniel Diniz (ajaksu2) (Python triager) Date: 2009-02-13 02:55
Is the issue valid? Can anyone implement a test based on Jean's description?
msg86342 - (view) Author: Guilherme Polo (gpolo) * (Python committer) Date: 2009-04-22 22:09
In theory at least, it is valid. I have done something similar in
another tcl <-> python bridge that I did for fun, but didn't achieve
good results in the end. From what I remember, creating a timer handler
instead of using a 20ms sleep complicates the releasing and acquiring
the GIL since you have to create a timer handler to fire now and release
the GIL, then schedule another to fire before any other event fires up
and acquire the GIL, and we would be creating timer handlers all the
time. It would have been better if I left this code in another branch of
that another bridge in order to compare the performance, but I'm really
unsure if this is going to give the improvement that OP is expecting.

Something that I would find interesting to see implemented is a
replacement of the Tcl Notifier, which I would expect to give us the
expected improvement here. Although Tcl is built to allow replacing its
notifier, it is also much more complex to do than doing what the OP is
requesting.

Now, in practice I would call this issue invalid (rejected actually).
There is no code/interest after almost 6 years, closing this now.
History
Date User Action Args
2009-04-22 22:09:09gpolosetstatus: open -> closed

nosy: + gpolo
messages: + msg86342

resolution: rejected
2009-02-13 02:55:38ajaksu2setnosy: + ajaksu2
stage: test needed
messages: + msg81856
versions: + Python 2.7
2003-07-31 00:14:58jbrouwerscreate