[IPython-dev] GUI support added.

Brian Granger ellisonbg at gmail.com
Fri Aug 27 00:54:21 EDT 2010

On Wed, Aug 25, 2010 at 11:01 PM, Fernando Perez
<Fernando.Perez at berkeley.edu> wrote:
> [ 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 <ellisonbg at gmail.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.
> Great.
>> * 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
>> catch!

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
>       else:
>           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!



> f

Brian E. Granger, Ph.D.
Assistant Professor of Physics
Cal Poly State University, San Luis Obispo
bgranger at calpoly.edu
ellisonbg at gmail.com

More information about the IPython-dev mailing list