Note that there are some explanatory texts on larger screens.

plurals
  1. POplotting / wxPython - Why is this call to MemoryDC.SelectObject() slow?
    primarykey
    data
    text
    <p>I'm attempting to do real-time plotting of data in matplotlib, in a "production" application that uses wxPython. I had been using Chaco for this purpose, but I'm trying to avoid Chaco in the future for many reasons, one of which is that since it's not well-documented I often must spend a long time reading the Chaco source code when I want to add even the smallest feature to one of my plots. One aspect where Chaco wins out over matplotlib is in speed, so I'm exploring ways to get acceptable performance from matplotlib.</p> <p>One technique I've seen widely used for fast plots in matplotlib is to set <code>animated</code> to <code>True</code> for elements of the plot which you wish to update often, then draw the background (axes, tick marks, etc.) only once, and use the <code>canvas.copy_from_bbox()</code> method to save the background. Then, when drawing a new <code>foreground</code> (the plot trace, etc.), you use <code>canvas.restore_region()</code> to simply copy the pre-rendered background to the screen, then draw the new foreground with <code>axis.draw_artist()</code> and <code>canvas.blit()</code> it to the screen.</p> <p>I wrote up a fairly simple example that embeds a FigureCanvasWxAgg in a wxPython Frame and tries to display a single trace of random data at 45 FPS. When the program is running with the Frame at the default size (hard-coded in my source), it achieves ~13-14 frames per second on my machine. When I maximize the window, the refresh drops to around 5.5 FPS. I don't think this will be fast enough for my application, especially once I start adding additional elements to be rendered in real-time.</p> <p>My code is posted here: <a href="https://gist.github.com/2630258" rel="nofollow">basic_fastplot.py</a></p> <p>I wondered if this could be made faster, so I profiled the code and found that by far the largest consumers of processing time are the calls to <code>canvas.blit()</code> at lines 99 and 109. I dug a little further, instrumenting the matplotlib code itself to find that most of this time is spent in a specific call to <code>MemoryDC.SelectObject()</code>. There are several calls to <code>SelectObject</code> in surrounding code, but only the one marked below takes any appreciable amount of time.</p> <p>From the matplotlib source, backend_wxagg.py:</p> <pre><code>class FigureCanvasWxAgg(FigureCanvasAgg, FigureCanvasWx): # ... def blit(self, bbox=None): """ Transfer the region of the agg buffer defined by bbox to the display. If bbox is None, the entire buffer is transferred. """ if bbox is None: self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None) self.gui_repaint() return l, b, w, h = bbox.bounds r = l + w t = b + h x = int(l) y = int(self.bitmap.GetHeight() - t) srcBmp = _convert_agg_to_wx_bitmap(self.get_renderer(), None) srcDC = wx.MemoryDC() srcDC.SelectObject(srcBmp) # &lt;&lt;&lt;&lt; Most time is spent here, 30milliseconds or more! destDC = wx.MemoryDC() destDC.SelectObject(self.bitmap) destDC.BeginDrawing() destDC.Blit(x, y, int(w), int(h), srcDC, x, y) destDC.EndDrawing() destDC.SelectObject(wx.NullBitmap) srcDC.SelectObject(wx.NullBitmap) self.gui_repaint() </code></pre> <p>My questions:</p> <ul> <li>What could SelectObject() be doing that is taking so long? I had sort of assumed it would just be setting up pointers, etc., not doing much copying or computation.</li> <li>Is there any way I might be able to speed this up (to get maybe 10 FPS at full-screen)?</li> </ul>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload