[Twisted-Python] threadedselectreactor and twistd

Hi, Just wondering how and if to integrate threadedselectreactor into twistd. I'm thinking to use it for a GUI application which is also a server (and a client), so I think using mktap/twistd makes sense, but there is the matter of threadedselectreactor not being supported. What I've been thinking is for threadedselectreactor to have another method, or it could be combined with interleave, that accepts a callable that makes the main loop run. It could also be a special reactor for, say, wxPython, that accepts a wxApp (and interleaves automatically), and calls its MainLoop method inside reactor.run(). This would make it trivial to use with twisted.application. It would simple require the service to let the reactor know about its wxApp/whatever. Any thoughts? Thanks, Antony Kummel __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

Not sure what you mean. If threadedselectreactor can't integrate with twistd, then the problem that threadedselectreactor solves is inherent to twistd, in which case twistd is simply unsuitable for some uses (i.e. GUI)? --- Bob Ippolito <bob@redivi.com> wrote:
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

The problem that it solves is inherent to the reactor API, and the implementations of those reactors. twistd supports the reactor API as-is, so it's not going to support an alternative to that API. But yes, twistd isn't really appropriate for the same kind of typical use cases that threadedselectreactor is. You're better off writing your app as you would normally do it, and invoking part of the twistd machinery yourself from inside there. What really needs to happen is that the reactor API needs to be refactored such that any reactor can be used as a threaded reactor. Right now the idea of the threaded*reactor and the select() backend are conflated. They don't have to be, and shouldn't, but I really didn't have the need to come up with such an API and change everything, I only needed one good implementation. -bob On Sep 12, 2005, at 11:28 AM, Antony Kummel wrote:

On 9/12/05, Antony Kummel <antonykummel@yahoo.com> wrote:
Antony, using twisted with GUIs is not trivial, and I found it quite tricky. But in the end it's possible and in fact I do it all the time. Here's the best solution I could find so far, using wxPython: 1) Run wxPython in the main thread 2) Run twisted reactor in a secondary thread 3) Have special proxy objects that bridge calls from gui code (running in one thread) and network code (running inside another) It doesn't sound nice, but it's not as bad as it seems. The problem is that there's not much you can do about it, really: first of all, wxPython is made in such a way that if you don't use its own event loop, you won't be able to use modal dialogs (which simply sucks). So you can't really use wxreactor, and similar solutions if you want to build anything more complex that hello world. Conversely, you can't use wxPython's event loop to process twisted events because it's not responsive enough. So you're left with the multiple threads solution only. Once you have this, you need to deal with the communication problem: say your network code is dealing with a protocol that fails, and you want to warn the used with an error dialog. You can't really call wx.ErrorDialog(...).ShowModal() because your code is running in the wrong thread, so you have to wx.CallAfter(myShowDialogMethod, ...). Similarly, if the user clicks on the "Connect" button, you can't call twisted code from within the OnClick() event handler because you're again in the wrong thread. Therefore you have to reactor.callFromThread(myBeginConnectionMethod, ...). So, dealing with these wx.CallAfter and reactor.callFromThread quickly urges you to write proxies whose methods are decorated in such a way that just by calling them from one thread triggers their execution in the other thread. When I discovered all these issues, I searched for code online and found something that I can't find again, but looks a lot like this (and could very well be the same): http://solipsis.netofpeers.net/wiki2/index.php/WxPython_And_Twisted_Example I wrote this in a bit of a rush, I hope I was clear enough. If this is relevant to you, let me know in case you need more info. stefano

On Tue, 13 Sep 2005 17:39:11 +0200, Stefano Masini <stefano@pragma2000.com> wrote:
using twisted with GUIs is not trivial, and I found it quite tricky. (...) using wxPython:
The problem here is not Twisted and GUIs, the problem is wxPython. While superficially appealing and very featureful, wxPython integrates *very* poorly with a foreign event loop and has no facility for integrating network I/O. Using GTK+ with Twisted, for example, is completely trivial, and requires no such threading hacks.

Never tried GTK with Twisted, but I don't understand how you can say that generally. Suppose a network event is taking some time to process (e.g. the protocol is complex and there are some calculations involved), then your GUI will become unresponsive (a 100ms delay is not critical for most Internet protocols, but it is for GUIs). Suppose there are lots of network events coming in, which flood the event loop for a short time. When will GUI events be processed ? Again, a 100ms delay will feel very annoying for the user (and more than 1 second delay is awful). On the other hand, if you have one thread for networking and one thread for the GUI, the OS can take care of the scheduling priorities naturally, using its sophisticated builtin mechanisms (e.g. noticing that one thread is "interactive" while the other is not), so you don't have to rewrite/emulate/composate for the lack of/ them. Am I missing something here ? Regards Antoine.

On Wed, 14 Sep 2005 13:35:35 +0200, Antoine Pitrou <solipsis@pitrou.net> wrote:
Never tried GTK with Twisted, but I don't understand how you can say that generally.
I was saying it was easier to program, not that it performed better (and by the way, it *does* perform better than WX), but since you asked -
Not at all. A user clicks on a button; if they don't see an update for 100ms, that is barely enough time for them to flick their mouse over to another button. In fact, network latency is such that it is nearly impossible to provide faster than 100ms actual real response time even for highly performance-critical applications. If the UI isn't redrawing for 100ms, it is hard for the user to even notice, unless it is a continuous 100ms between redraws, in which case this GUI application is really doing quite a lot of work!
A news aggregator I use, straw, does blocking DNS lookups and can hang completely for upwards of a minute while it's doing an update. While this is not exactly ideal behavior, it's tolerable. Even Firefox locks up for a few seconds when rendering a complex page. You are somewhat overstating the case - I sure wish that everything were faster, but 100ms latency on certain operations is not going to make anyone stop using an application :).
Am I missing something here ?
A few things: 1 - this is really not as major a problem as you say, for the reasons given above. 2 - this argument is tangential; if the thread scheduler is so sophisticated, it will notice that the IO-plus-UI thread is also "interactive" and schedule it appropriately. (In fact, both threads in your example are "interactive" according to Linux 2.6's scheduler heuristic, I think) 3 - you don't have to emulate anything about threads when writing Twisted GUI applications unless you have extremely computation-intensive actions to perform; and in that case you can use threads for those (few) actions rather than everything in the app 4 - you're assuming that you have to build extra to "compensate" for the lack of threads, but you're ignoring the cost of building support tools to use them. building thread safety into even a single API is difficult, costly, and extremely hard to test for correctness even superficially. 5 - if you have a networked interactive application under high load, you are not going to improve performance or interactivity by performing a ton of additional context switches as well as a bunch of extra work locking and unlocking shared mutexes. smart as the scheduler is, your computer *does* only have one or two processors, and more threads = more work. (this is especially true if you are using threads for EVERYTHING in your application, rather than just the truly parallelizeable tasks) 6 - in Python, your threaded work has to release the GIL to give any substantive improvement in performance, which it probably doesn't. ... and that's just off the top of my head.

Hi,
Of course, but in a non-trivial GUI+network application, lots of GUI actions do not imply networking. For example in Firefox, the bookmarks editor is independent from networking stuff, and I doubt it is unresponsive when the app is busy parsing some HTML (I must admit I haven't checked, though).
That tolerance certainly depends on the user ;) People who aren't aware of network issues will just think "wow, it's crashed" and kill the window in a way or another.
6 - in Python, your threaded work has to release the GIL to give any substantive improvement in performance, which it probably doesn't.
My argument was only about responsiveness (latency), not performance (bandwidth). Also, I advocate the use of two threads, not a thousand ;)) (er... I will try to find the time to look at Q2Q, by the way) Regards Antoine.

Oh good, a tangential conversation that I'm not really qualified to comment on with no real significance to the subject of the list. My favourite! I must add my two cents. ;-) On Wed September 14 2005 08:05, glyph@divmod.com wrote:
100ms seems like an awfully long time for a GUI to go without even providing feedback to the user (ie, depressing a button, colouring a link, highlighting a control, etc). Consider especially operations like drag-and-drop and using spinners, which are very interactive and require fine motor movement. Also consider interacting with dense and complex controls with lots of small clicking areas, as in a DTP app or 3d modeller. Timely feedback is very important to a comfortable experience. After 8 hours of using something with mushy, >100ms feedback, I would be cursing the invention of the mouse. I drank deeply of the Be koolaid. I think the goal should be for an interface should remain responsive at interactive levels in all conditions, even when the rest of the app is busy and unresponsive. Feedback to user actions should seem instantaneous (much closer to 10ms than 100ms), even -- especially! -- if the user's actions cannot be resolved for some seconds.
10fps is a pretty feeble goal in a lot of application spaces. Of course, I recognize that Twisted is a framework for network apps, not UIs. But that's almost an argument *for* separating the UI and network event loops.
"These other apps suck, so ours can suck too"?
I use Konq rather than Firefox because, on my turn-of-the-century equipment, Firefox is too unresponsive. Of course, I sacrifice a lot of the "web experience" but a) good riddance and b) unresponsive apps aggravate me, perhaps more than the average user.
A few things:
Though I disagree with your assumptions, I can't argue with your points. I'm tempted to think this is a failing of Python (the heresy!). It seems like because of issues like the GIL, one needs to put the interface and the machinery in completely separate processes to reach Be-like ideals. Mike.

Mike Pelletier wrote:
Oh my, a good idea hidden inside this futile thread. Use separate processes for heavy loads of different characteristics. Use a clean protocol between the processes to enable pluggability of things you never even imagined.

glyph@divmod.com wrote:
Normally you're a pretty sharp guy, but you're dead wrong about this. Tenth of a second delays are very noticeable, quickly become quite annoying, and make fine GUI control difficult as your mouse jumps around, etc.. Keeping interupts shorter than 100ms is very much critical for GUIs. Your "Firefox is unresponsive" example is a special case, as usually there is nothing to do while you wait for a page to load, so lack of responsiveness goes unnoticed; even so, as soon as you try loading multiple pages in background tabs it can become quite annoying, with mouse clicks get lost, etc. Now, I'm not a fan of threaded programming, and I definitely agree wxPython doesn't integrate well with Twisted (IIRC it doesn't relinquish control reliably), but Twisted is also lacking in this department. I only see 2 ways to deal with moderate length processing chunks and still allow a responsive GUI: split them off into a seperate thread/process (yuck!), or painstakingly instrument every such piece of code to do it's own time tracking and yield at an appropriate moment -- which isn't much better than threading. Worse, I don't see a satisfactory way to deal with the problem if it stems from some internal bit of Twisted taking too big of a time slice. Manually split and recombine my network data into smaller chunks? Run the whole GUI loop in a different thread?! Unfortunately I don't have a solid idea of what Twisted could do better here, as I'm only passingly familiar with it's internals. Perhaps some way to get the Reactor to transmit network data in smaller chunks, with more frequent pauses in between to allow for GUI responsiveness? -Jasper

Two noticeable cases of that are (de)serialization in PB and in XML-RPC code. Is there going to be any facility, in newpb, for splitting up (de)serialization in small chunks? -- Nicola Larosa - nico@tekNico.net That's a bit too much navel-gazing for me. With enough effort, you make anything a symbol of anything else. But that doesn't get any code written. -- Robert Kern on comp.lang.python, July 2005

On 9/15/05, Nicola Larosa <nico@teknico.net> wrote:
Thinking about event handling taking up too much time, I once hacked my reactor in order to measure the time taken by each callback and send warnings when the execution time was longer than 0.something... I found it useful to track down some horrible implementation that I left behind and forgot about. Is there something like this somewhere in twisted? Maybe something that could be turned on and off for debugging? Of course this would mean extra work at every cycle. Would it be too bad for performance? I didn't find my hack too bad, but I wasn't working at critical throughputs, I was just concerned with responsiveness. cheers, stefano

Nicola Larosa wrote:
Yes, PB (de)serialization seems to be where I get responsiveness burps too. I can split up large processing chunks of my own (probably along the line of JP's Cooperator), but I don't see how to readily do that to delays that are internal to Twisted, without maintaining my own version or shunting all networking into a seperate thread (which I'm loath to do). -Jasper

On 9/14/05, glyph@divmod.com <glyph@divmod.com> wrote:
[etc, etc, all of glyph's points...] Whether or not this argument is correct, it's unnecessary. There's a much simpler way to argue this side of the threads-in-GUIs debate: The way to write all Twisted applications, not just GUI ones, is that you _DO NOT BLOCK_. Blocking for even a small amount of time in, for example, a network server application, can eventually have disastrous results for the usability of your network server application. If you have CPU intensive functionality in your application, you need to figure out a way to make it not block, by either (e.g.) breaking the computation across reactor iterations, or by deferring those individual operations to a thread, or process, or whatever. For other sorts of operations, fortunately Twisted offers non-blocking alternatives for many sorts of operations, like I/O. :-) If you write your Twisted application in a way that isn't horrible, your GUIs won't block. It's pretty simple. -- Twisted | Christopher Armstrong: International Man of Twistery Radix | -- http://radix.twistedmatrix.com | Release Manager, Twisted Project \\\V/// | -- http://twistedmatrix.com |o O| | w----v----w-+

Christopher Armstrong wrote:
If you write your Twisted application in a way that isn't horrible, your GUIs won't block. It's pretty simple.
I was about to write a post that looked about like this, and that also made reference to the "cooperator" module that JP just posted, so thank you both for making that irrelevant :)

Provided it is a network server application, that is. If you are writing an asynchronous message-passing-based P2P app, then a 100ms or even 1s latency when sending/receiving packets isn't horrible at all. But it becomes horrible when the GUI is subject to the same 100ms delay ;) Regards Antoine.

On 9/15/05, Antoine Pitrou <solipsis@pitrou.net> wrote:
I don't see your point Antoine. Chris was pointing out that in an asynchronous model your event handlers should not block. This means that if the task you're performing - say round tripping a packet - is gonna take 100ms, instead of waiting for it to complete - as you would in a synchronous model - you're gonna break it up into, say, "initiation" and "completion" phases. So your handler will only block for the duration of the initiation phase, that will supposedly last a lot less that 100ms, maybe not more than 1ms, and return a deferred. Then the event loop will go off and do other stuff. After 100 ms the deferred will fire and some other part of your code will be called and perform the completion phase. So, if you do as you should, GUI responsiveness will not have anything to deal with the actual round trip times of your protocol messages. The problem with responsiveness will come up _only_ if for some reason you have handlers that take a lot of time to run. For example if they do complex computation or synchronous IO of large files, and stuff like this. stefano

Itamar Shtull-Trauring wrote:
Do you guys plan on making a release of Twisted that contains threadedselectreactor? One of the reasons I hate using it is that every time I want to develop on a Windows box, I have to grab the free Visual Studio compiler, a bunch of SDKs, patch distutils to support the free compiler, compile Zope.Interface and Twisted just to use the threadedselectreactor. It's been working really well for us, by the way. Dave

On 9/13/05, Bob Ippolito <bob@redivi.com> wrote:
Have you actually used threadedselectreactor? It sure doesn't sound like it. It solves this problem without the proxy objects.
Indeed, I just learn about it now. Thanks! It sounds sweet. Unfortunately I've already got a lot of working code... proxy objects aren't that bad for me. So I'll have to wait until the next refactoring in order to try it. :( -stefano

Not sure what you mean. If threadedselectreactor can't integrate with twistd, then the problem that threadedselectreactor solves is inherent to twistd, in which case twistd is simply unsuitable for some uses (i.e. GUI)? --- Bob Ippolito <bob@redivi.com> wrote:
__________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com

The problem that it solves is inherent to the reactor API, and the implementations of those reactors. twistd supports the reactor API as-is, so it's not going to support an alternative to that API. But yes, twistd isn't really appropriate for the same kind of typical use cases that threadedselectreactor is. You're better off writing your app as you would normally do it, and invoking part of the twistd machinery yourself from inside there. What really needs to happen is that the reactor API needs to be refactored such that any reactor can be used as a threaded reactor. Right now the idea of the threaded*reactor and the select() backend are conflated. They don't have to be, and shouldn't, but I really didn't have the need to come up with such an API and change everything, I only needed one good implementation. -bob On Sep 12, 2005, at 11:28 AM, Antony Kummel wrote:

On 9/12/05, Antony Kummel <antonykummel@yahoo.com> wrote:
Antony, using twisted with GUIs is not trivial, and I found it quite tricky. But in the end it's possible and in fact I do it all the time. Here's the best solution I could find so far, using wxPython: 1) Run wxPython in the main thread 2) Run twisted reactor in a secondary thread 3) Have special proxy objects that bridge calls from gui code (running in one thread) and network code (running inside another) It doesn't sound nice, but it's not as bad as it seems. The problem is that there's not much you can do about it, really: first of all, wxPython is made in such a way that if you don't use its own event loop, you won't be able to use modal dialogs (which simply sucks). So you can't really use wxreactor, and similar solutions if you want to build anything more complex that hello world. Conversely, you can't use wxPython's event loop to process twisted events because it's not responsive enough. So you're left with the multiple threads solution only. Once you have this, you need to deal with the communication problem: say your network code is dealing with a protocol that fails, and you want to warn the used with an error dialog. You can't really call wx.ErrorDialog(...).ShowModal() because your code is running in the wrong thread, so you have to wx.CallAfter(myShowDialogMethod, ...). Similarly, if the user clicks on the "Connect" button, you can't call twisted code from within the OnClick() event handler because you're again in the wrong thread. Therefore you have to reactor.callFromThread(myBeginConnectionMethod, ...). So, dealing with these wx.CallAfter and reactor.callFromThread quickly urges you to write proxies whose methods are decorated in such a way that just by calling them from one thread triggers their execution in the other thread. When I discovered all these issues, I searched for code online and found something that I can't find again, but looks a lot like this (and could very well be the same): http://solipsis.netofpeers.net/wiki2/index.php/WxPython_And_Twisted_Example I wrote this in a bit of a rush, I hope I was clear enough. If this is relevant to you, let me know in case you need more info. stefano

On Tue, 13 Sep 2005 17:39:11 +0200, Stefano Masini <stefano@pragma2000.com> wrote:
using twisted with GUIs is not trivial, and I found it quite tricky. (...) using wxPython:
The problem here is not Twisted and GUIs, the problem is wxPython. While superficially appealing and very featureful, wxPython integrates *very* poorly with a foreign event loop and has no facility for integrating network I/O. Using GTK+ with Twisted, for example, is completely trivial, and requires no such threading hacks.

Never tried GTK with Twisted, but I don't understand how you can say that generally. Suppose a network event is taking some time to process (e.g. the protocol is complex and there are some calculations involved), then your GUI will become unresponsive (a 100ms delay is not critical for most Internet protocols, but it is for GUIs). Suppose there are lots of network events coming in, which flood the event loop for a short time. When will GUI events be processed ? Again, a 100ms delay will feel very annoying for the user (and more than 1 second delay is awful). On the other hand, if you have one thread for networking and one thread for the GUI, the OS can take care of the scheduling priorities naturally, using its sophisticated builtin mechanisms (e.g. noticing that one thread is "interactive" while the other is not), so you don't have to rewrite/emulate/composate for the lack of/ them. Am I missing something here ? Regards Antoine.

On Wed, 14 Sep 2005 13:35:35 +0200, Antoine Pitrou <solipsis@pitrou.net> wrote:
Never tried GTK with Twisted, but I don't understand how you can say that generally.
I was saying it was easier to program, not that it performed better (and by the way, it *does* perform better than WX), but since you asked -
Not at all. A user clicks on a button; if they don't see an update for 100ms, that is barely enough time for them to flick their mouse over to another button. In fact, network latency is such that it is nearly impossible to provide faster than 100ms actual real response time even for highly performance-critical applications. If the UI isn't redrawing for 100ms, it is hard for the user to even notice, unless it is a continuous 100ms between redraws, in which case this GUI application is really doing quite a lot of work!
A news aggregator I use, straw, does blocking DNS lookups and can hang completely for upwards of a minute while it's doing an update. While this is not exactly ideal behavior, it's tolerable. Even Firefox locks up for a few seconds when rendering a complex page. You are somewhat overstating the case - I sure wish that everything were faster, but 100ms latency on certain operations is not going to make anyone stop using an application :).
Am I missing something here ?
A few things: 1 - this is really not as major a problem as you say, for the reasons given above. 2 - this argument is tangential; if the thread scheduler is so sophisticated, it will notice that the IO-plus-UI thread is also "interactive" and schedule it appropriately. (In fact, both threads in your example are "interactive" according to Linux 2.6's scheduler heuristic, I think) 3 - you don't have to emulate anything about threads when writing Twisted GUI applications unless you have extremely computation-intensive actions to perform; and in that case you can use threads for those (few) actions rather than everything in the app 4 - you're assuming that you have to build extra to "compensate" for the lack of threads, but you're ignoring the cost of building support tools to use them. building thread safety into even a single API is difficult, costly, and extremely hard to test for correctness even superficially. 5 - if you have a networked interactive application under high load, you are not going to improve performance or interactivity by performing a ton of additional context switches as well as a bunch of extra work locking and unlocking shared mutexes. smart as the scheduler is, your computer *does* only have one or two processors, and more threads = more work. (this is especially true if you are using threads for EVERYTHING in your application, rather than just the truly parallelizeable tasks) 6 - in Python, your threaded work has to release the GIL to give any substantive improvement in performance, which it probably doesn't. ... and that's just off the top of my head.

Hi,
Of course, but in a non-trivial GUI+network application, lots of GUI actions do not imply networking. For example in Firefox, the bookmarks editor is independent from networking stuff, and I doubt it is unresponsive when the app is busy parsing some HTML (I must admit I haven't checked, though).
That tolerance certainly depends on the user ;) People who aren't aware of network issues will just think "wow, it's crashed" and kill the window in a way or another.
6 - in Python, your threaded work has to release the GIL to give any substantive improvement in performance, which it probably doesn't.
My argument was only about responsiveness (latency), not performance (bandwidth). Also, I advocate the use of two threads, not a thousand ;)) (er... I will try to find the time to look at Q2Q, by the way) Regards Antoine.

Oh good, a tangential conversation that I'm not really qualified to comment on with no real significance to the subject of the list. My favourite! I must add my two cents. ;-) On Wed September 14 2005 08:05, glyph@divmod.com wrote:
100ms seems like an awfully long time for a GUI to go without even providing feedback to the user (ie, depressing a button, colouring a link, highlighting a control, etc). Consider especially operations like drag-and-drop and using spinners, which are very interactive and require fine motor movement. Also consider interacting with dense and complex controls with lots of small clicking areas, as in a DTP app or 3d modeller. Timely feedback is very important to a comfortable experience. After 8 hours of using something with mushy, >100ms feedback, I would be cursing the invention of the mouse. I drank deeply of the Be koolaid. I think the goal should be for an interface should remain responsive at interactive levels in all conditions, even when the rest of the app is busy and unresponsive. Feedback to user actions should seem instantaneous (much closer to 10ms than 100ms), even -- especially! -- if the user's actions cannot be resolved for some seconds.
10fps is a pretty feeble goal in a lot of application spaces. Of course, I recognize that Twisted is a framework for network apps, not UIs. But that's almost an argument *for* separating the UI and network event loops.
"These other apps suck, so ours can suck too"?
I use Konq rather than Firefox because, on my turn-of-the-century equipment, Firefox is too unresponsive. Of course, I sacrifice a lot of the "web experience" but a) good riddance and b) unresponsive apps aggravate me, perhaps more than the average user.
A few things:
Though I disagree with your assumptions, I can't argue with your points. I'm tempted to think this is a failing of Python (the heresy!). It seems like because of issues like the GIL, one needs to put the interface and the machinery in completely separate processes to reach Be-like ideals. Mike.

Mike Pelletier wrote:
Oh my, a good idea hidden inside this futile thread. Use separate processes for heavy loads of different characteristics. Use a clean protocol between the processes to enable pluggability of things you never even imagined.

glyph@divmod.com wrote:
Normally you're a pretty sharp guy, but you're dead wrong about this. Tenth of a second delays are very noticeable, quickly become quite annoying, and make fine GUI control difficult as your mouse jumps around, etc.. Keeping interupts shorter than 100ms is very much critical for GUIs. Your "Firefox is unresponsive" example is a special case, as usually there is nothing to do while you wait for a page to load, so lack of responsiveness goes unnoticed; even so, as soon as you try loading multiple pages in background tabs it can become quite annoying, with mouse clicks get lost, etc. Now, I'm not a fan of threaded programming, and I definitely agree wxPython doesn't integrate well with Twisted (IIRC it doesn't relinquish control reliably), but Twisted is also lacking in this department. I only see 2 ways to deal with moderate length processing chunks and still allow a responsive GUI: split them off into a seperate thread/process (yuck!), or painstakingly instrument every such piece of code to do it's own time tracking and yield at an appropriate moment -- which isn't much better than threading. Worse, I don't see a satisfactory way to deal with the problem if it stems from some internal bit of Twisted taking too big of a time slice. Manually split and recombine my network data into smaller chunks? Run the whole GUI loop in a different thread?! Unfortunately I don't have a solid idea of what Twisted could do better here, as I'm only passingly familiar with it's internals. Perhaps some way to get the Reactor to transmit network data in smaller chunks, with more frequent pauses in between to allow for GUI responsiveness? -Jasper

Two noticeable cases of that are (de)serialization in PB and in XML-RPC code. Is there going to be any facility, in newpb, for splitting up (de)serialization in small chunks? -- Nicola Larosa - nico@tekNico.net That's a bit too much navel-gazing for me. With enough effort, you make anything a symbol of anything else. But that doesn't get any code written. -- Robert Kern on comp.lang.python, July 2005

On 9/15/05, Nicola Larosa <nico@teknico.net> wrote:
Thinking about event handling taking up too much time, I once hacked my reactor in order to measure the time taken by each callback and send warnings when the execution time was longer than 0.something... I found it useful to track down some horrible implementation that I left behind and forgot about. Is there something like this somewhere in twisted? Maybe something that could be turned on and off for debugging? Of course this would mean extra work at every cycle. Would it be too bad for performance? I didn't find my hack too bad, but I wasn't working at critical throughputs, I was just concerned with responsiveness. cheers, stefano

Nicola Larosa wrote:
Yes, PB (de)serialization seems to be where I get responsiveness burps too. I can split up large processing chunks of my own (probably along the line of JP's Cooperator), but I don't see how to readily do that to delays that are internal to Twisted, without maintaining my own version or shunting all networking into a seperate thread (which I'm loath to do). -Jasper

On 9/14/05, glyph@divmod.com <glyph@divmod.com> wrote:
[etc, etc, all of glyph's points...] Whether or not this argument is correct, it's unnecessary. There's a much simpler way to argue this side of the threads-in-GUIs debate: The way to write all Twisted applications, not just GUI ones, is that you _DO NOT BLOCK_. Blocking for even a small amount of time in, for example, a network server application, can eventually have disastrous results for the usability of your network server application. If you have CPU intensive functionality in your application, you need to figure out a way to make it not block, by either (e.g.) breaking the computation across reactor iterations, or by deferring those individual operations to a thread, or process, or whatever. For other sorts of operations, fortunately Twisted offers non-blocking alternatives for many sorts of operations, like I/O. :-) If you write your Twisted application in a way that isn't horrible, your GUIs won't block. It's pretty simple. -- Twisted | Christopher Armstrong: International Man of Twistery Radix | -- http://radix.twistedmatrix.com | Release Manager, Twisted Project \\\V/// | -- http://twistedmatrix.com |o O| | w----v----w-+

Christopher Armstrong wrote:
If you write your Twisted application in a way that isn't horrible, your GUIs won't block. It's pretty simple.
I was about to write a post that looked about like this, and that also made reference to the "cooperator" module that JP just posted, so thank you both for making that irrelevant :)

Provided it is a network server application, that is. If you are writing an asynchronous message-passing-based P2P app, then a 100ms or even 1s latency when sending/receiving packets isn't horrible at all. But it becomes horrible when the GUI is subject to the same 100ms delay ;) Regards Antoine.

On 9/15/05, Antoine Pitrou <solipsis@pitrou.net> wrote:
I don't see your point Antoine. Chris was pointing out that in an asynchronous model your event handlers should not block. This means that if the task you're performing - say round tripping a packet - is gonna take 100ms, instead of waiting for it to complete - as you would in a synchronous model - you're gonna break it up into, say, "initiation" and "completion" phases. So your handler will only block for the duration of the initiation phase, that will supposedly last a lot less that 100ms, maybe not more than 1ms, and return a deferred. Then the event loop will go off and do other stuff. After 100 ms the deferred will fire and some other part of your code will be called and perform the completion phase. So, if you do as you should, GUI responsiveness will not have anything to deal with the actual round trip times of your protocol messages. The problem with responsiveness will come up _only_ if for some reason you have handlers that take a lot of time to run. For example if they do complex computation or synchronous IO of large files, and stuff like this. stefano

Itamar Shtull-Trauring wrote:
Do you guys plan on making a release of Twisted that contains threadedselectreactor? One of the reasons I hate using it is that every time I want to develop on a Windows box, I have to grab the free Visual Studio compiler, a bunch of SDKs, patch distutils to support the free compiler, compile Zope.Interface and Twisted just to use the threadedselectreactor. It's been working really well for us, by the way. Dave

On 9/13/05, Bob Ippolito <bob@redivi.com> wrote:
Have you actually used threadedselectreactor? It sure doesn't sound like it. It solves this problem without the proxy objects.
Indeed, I just learn about it now. Thanks! It sounds sweet. Unfortunately I've already got a lot of working code... proxy objects aren't that bad for me. So I'll have to wait until the next refactoring in order to try it. :( -stefano
participants (13)
-
Antoine Pitrou
-
Antony Kummel
-
Bob Ippolito
-
Christopher Armstrong
-
David E. Konerding DSD staff
-
Glyph Lefkowitz
-
glyph@divmod.com
-
Itamar Shtull-Trauring
-
Jasper
-
Mike Pelletier
-
Nicola Larosa
-
Stefano Masini
-
Tommi Virtanen