[IPython-dev] GUI support added.
Thu Aug 26 23:54:21 CDT 2010
On Wed, Aug 25, 2010 at 11:01 PM, Fernando Perez
> [ Cc-ing the dev list so the power figures below get recorded where
> Google will find them ]
> On Wed, Aug 25, 2010 at 22:08, Brian Granger <email@example.com> wrote:
>> I just pushed GUI support for Qt, Tk and Wx into ipython/newkernel. I
>> think we are doing pretty good overall with the GUI support for now.
>> We just need lots of testing. I have tried many of the matplotlib
>> examples and most of them work fine. Evan, if you can try some big
>> trait apps, that would be great. We should also try some Mayavi
>> examples as well. Right now I have tuned the polling time on the GUI
>> timers so that the CPU usage is below 1% for the kernel. This is
>> about what the frontend itself is as well.
> This is fantastic, great job!
> As I mentioned before, CPU load isn't the only metric we need to look
> at, the key one is the number of CPU wakeups-from-idle per second
> induced by an app, that's what kills battery life. A linux laptop
> running on battery (you don't get this info on AC power) has the
> 'powertop' utility written by Intel to show who's keeping the CPU
> awake. Some numbers I've seen from quick testing on my new laptop
> (core i5 ultra low voltage, running in 'powersave' mode):
> - plain python shell: doesn't even register in powertop.
> - IPython 0.10.1, no pylab/thread support: same
> - IPython 0.10.1, with pylab using qt4 backend: same
> - IPython 0.10.1, with pylab using Wx backend: 10 wakeups per second.
> - IPython newkernel at the terminal (no zmq), no pylab: doesn't register
> - IPython newkernel at the terminal (no zmq), with pylab/qt4: same
This is quite good new. I am glad the Qt stuff looks good. I am not
too surprised though because the Qt inputhook does not do the polling
that the wx one does.
> This is *fantastic* news. I'm not sure what changes are in the code
> that may explain this, but it seems that the one-process one (with
> pyosinputhook and qt4) is behaving better than I remember it from a
> while ago. Maybe it's just my memory, but I seem to recall it showed
> up more in powertop. Or maybe not, Qt has been OK all along and it's
> Wx that's the bad guy:
> - IPython newkernel at the terminal (no zmq), with pylab/wx: bad news:
> ~50 wakeups per second, the worst offender program in the whole
> computer, only second to the (linux) kernel itself.
> Indeed, Wx is bad: with -wthread it already gave ~10 wakeups per
> second, and with PyOSInputHook it's ~50. Nasty... Basically, Wx is a
> wakeup hog that will kill any battery.
> The good news is that in one process, even Qt is very well behaved and
> gives no detectable power signature.
> Now, when we run ipythonqt, which brings out two processes, messages
> flying around and a full qt app, we do eat more power. Here are the
> numbers (in all cases we have the Qt app for the frontend, zmq, and
> possibly some gui toolkit active in the kernel):
> - no pylab: ~37
> - pylab tk: same
> - pylab qt: same
> - pylab wx: same
Fernando, this is great that you looked at these stats. It is really
helpful to get an idea of this. But, I would like to know if the
issue is from the frontend or the kernel. Is there any chance you
could repeat the 2 process tests and get separate stats for the
frontend and kernel. I think we may be able to improve the situation,
but I first need to know which process to look at.
> The good news from this: enabling gui support in the new system has no
> net power cost. The bad news: even with no gui support, the power
> signature of the combined qt frontend/zmq communications/2 processes
> is pretty noticeable.
> One more reason to keep around the lightweight one-process guy: if
> you're on a plane trying to get every last ounce of battery out, it's
> a good option. Similar to how I switch window managers from Gnome to
> Awesome when I need to maximize battery life, this simply means that
> we'll have a range of interface options. The fancier ones have a
> power cost, and the more spartan ones will be very efficient.
>> Some notes:
>> * Wx and Tk work out of the box with the matplotlib in EPD.
>> * For Qt, we are going to have to patch matplotlib. I am attaching my
>> patched qt backend. This is just a draft of the patch and we may have
>> to add additional logic.
> OK, let's work on this one a bit, and when ready we'll get in touch with MPL.
I submitted a patch tonight for that stuff.
>> * During the process of merging with newkernel I found some things:
>> - The default color scheme for the crash handler was set to Linux.
>> I have changed this to LightBR on the Mac so the crash tracebacks are
>> not invisible.
> Yes, good call. Sorry I forgot to do that yesterday, I enabled it and
> never went back to clean it up.
>> - I ran PyFlakes on some files and found some bugs (ultratb,
>> entry_point, etc.). These bugs were not discovered because they were
>> in parts of the code
>> that are not run usually. Let's make it a habit of running
>> PyFlakes before any merge. It is amazing the things that it will
Yes, it is a pretty nifty tool.
> Yup, good point! I keep it on my Emacs setup all the time, I just
> forgot to run it (it's just a keystroke, I don't know why I got out of
> the habit). Pyflakes is definitely something to run regularly.
>> - The names rprint/rprinte are great for quick debugging shortcuts.
>> But these are now showing up in production code. Could we alias them
>> to raw_print_out and
>> raw_print_err and use the longer names in production code so 6
>> months from now we don't have to go looking up what these functions
>> do? I am fine keeping the
>> short names around for quick debugging though.
> Yup. In fact, I'll rename them just raw_print and raw_print_err, the
> normal one doesn't really need a separate name.
Sounds good, thanks.
>> # Patch to backend_qt4.py
>> # I have changed the _create_aApp function to the following:
> def _create_qApp():
> Only one qApp can exist at a time, so check before creating one.
> if QtGui.QApplication.startingUp():
> if DEBUG: print "Starting up QApplication"
> global qApp
> app = QtGui.QApplication.instance()
> if app is None:
> qApp = QtGui.QApplication( [" "] )
> QtCore.QObject.connect( qApp, QtCore.SIGNAL( "lastWindowClosed()" ),
> qApp, QtCore.SLOT( "quit()" ) )
> #remember that matplotlib created the qApp - will be used by show()
> _create_qApp.qAppCreatedHere = True
> qApp = app
> _create_qApp.qAppCreatedHere = False
> OK, we'll pound on the Qt code a little more until it feels robust.
> Cheers, and thanks again for the great job!
Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
More information about the IPython-dev