[IPython-dev] GUI support added.
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.
>> * 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
bgranger at calpoly.edu
ellisonbg at gmail.com
More information about the IPython-dev