Re: [wxPython] DrawLines and a bunch points
by bryan cole other posts by this author
May 1 2002 8:21AM messages near this date
Re: [wxPython] DrawLines and a bunch points
|
Re: [wxPython] DrawLines and a bunch points
Just tried your test-script on my linux box: I always get a value of
between 0.1 and 0.15 (wxGTK/wxPython 2.3.2-1, RHlinux7.1, 500MHz PIII,
no graphics card)
Bryan
On Mon, 2002-04-29 at 23:37, eric wrote:
> Hello,
>
> I've run into an issue when drawing a line with a large number of points using
> DrawLines. I've attached code below that simply draws a Numeric array of 30000
> points into a window. When the window is resized, it regenerates the point list
> and draws the points again. When the 30000 points are initially drawn to the
> window, they are very fast (.07 seconds), but subsequent draws after a resize
> are much slower (sometimes 2 orders of magnitude. Here is the output from my
> little test script when using DrawLines. The first timing is when the window
> initially appears. The others are after a resize. This is using wxPython2.3.2
> with Python 2.1.3 on windows 2000.
>
> C:\home\ej\wrk\chaco>python faster.py
> 30001
> wxPython DrawLines: 0.0752268793939
> 30000
> wxPython DrawLines: 0.327031508194
> 30000
> wxPython DrawLines: 6.30562264198
> 30000
> wxPython DrawLines: 6.32888677192
> 30000
> wxPython DrawLines: 4.22979680378
>
> I thought maybe the wxPython overhead was the problem, so I used weave.inline to
> bypass the wxPython stuff and draw the win32 PolyLine API routine directly. I
> got the same lousy result.
>
> C:\home\ej\wrk\chaco>python faster.py
> 30001
> str: _1878900_wxPaintDC_p <weave debug output>
> Call to Polyline: 1.30914739164 <slower due to loading a dll>
> 30001
> str: _1878900_wxPaintDC_p
> Call to Polyline: 0.285114728269
> 30000
> str: _1878900_wxPaintDC_p
> Chunked calls to Polyline: 5.18981490664
> 30000
> str: _1878900_wxPaintDC_p
> Call to Polyline: 0.327584651122
> 30001
> str: _1878900_wxPaintDC_p
> Call to Polyline: 6.85253796223
> 30000
> str: _1878900_wxPaintDC_p
> Call to Polyline: 4.44026182099
>
> Further poking around showed that the slow down was much worse than linear with
> the number of points being drawn. This seemed wierd, but I went ahead and set
> things up to draw the line in small chunks of 100 points to see if that helped.
> It did in a major way.
>
> C:\home\ej\wrk\chaco>python faster.py
> 30001
> str: _1878900_wxPaintDC_p
> Chunked calls to Polyline: 1.49216897678 <slow because it is loading a DLL>
> 30000
> str: _1878900_wxPaintDC_p
> Chunked calls to Polyline: 0.199176990372
> 30000
> str: _1878900_wxPaintDC_p
> Chunked calls to Polyline: 0.318512827748
> 30000
> str: _1878900_wxPaintDC_p
> Chunked calls to Polyline: 0.316748078317
> 30000
> str: _1878900_wxPaintDC_p
> Chunked calls to Polyline: 0.266672160847
>
> All this background to ask some non-wxPython questions (though related...):
>
> 1. Can anyone verify that they get the same behavior with
> DrawLines? <I wondering if something is strange about
> my machine setup>
> Verifying the weave behavior requires a CVS version of
> weave -- I'm less interested in this, and it'll require
> effort.
>
> 2. Does anyone have any insight into what is going on here?
>
> a. Why is PolyLine fast for the initial call and slow for
> subsequent calls with a large number of points?
>
> b. Why is PolyLine slow for a large number of points?
> Heck, 30000 isn't even all that large of a number.
>
> 3. Does Linux have the same problem?
>
> 4. Am I missing an extra call somewhere that would fix all my
> problems?
>
> The code below is the demo. It does require Numeric, but doesn't require
> weave unless you restore the commented out code in the OnPaint routine.
> As a side benefit, it does show a nice example of how to use weave with
> wxPython.
>
> thanks for any hints,
>
> eric
>
> --
> Eric Jones <eric at enthought.com>
> Enthought, Inc. [www.enthought.com and www.scipy.org]
> (512) 536-1057
>
> """ Implements a fast replacement for calling DrawLines with an array as an
> argument. It uses weave, so you'll need that installed.
>
> I wrote this because I was seeing very bad performance for DrawLines when
> called with a large number of points -- 5000-30000. Now, I have found the
> performance is sometimes OK, and sometimes very poor. Drawing to a
> MemoryDC seems to be worse than drawing to the screen. My first cut of the
> routine just called PolyLine directly, but I got lousy performance for this
> also. After noticing the slowdown as the array length grew was much worse
> than linear, I tried the following "chunking" algorithm. It is much more
> efficient (sometimes by 2 orders of magnitude, but usually only a factor
> of 3). There is a slight drawback in that it will draw end caps for each
> chunk of the array which is not strictly correct. I don't imagine this is
> a major issue, but remains an open issue.
>
> """
>
> from Numeric import *
>
> polyline_code = > """
> // uses a grouping approach because drawing seems to be veeery slow for
> // a large number of lines.
> // Hmmm. Further inspection shows that this isn't always the case, but
> // don't have the time to track down the causes. It seems to always be
> // fast using this algorithm.
>
> int *p_data = line_data;
> HDC hdc = (HDC) dc->GetHDC();
>
> const int n_pts = _Nline[0];
> const int bunch_size = 100;
> const int bunches = n_pts / bunch_size;
> const int left_over = n_pts % bunch_size;
>
> for (int i = 0; i < bunches; i++)
> {
> Polyline(hdc,(POINT*)p_data,bunch_size);
> p_data += bunch_size*2; //*2 for two longs per point
> }
> Polyline(hdc,(POINT*)p_data,left_over);
> """
>
> def polyline(dc,line):
> """
> """
> import weave
>
> shp = line.shape
> assert(len(shp)==2 and shp[1] == 2)
> if (line.typecode() != Int32 or
> not line.iscontiguous()):
> line = line.astype(Int32)
> weave.inline(polyline_code,['dc','line'])
>
> if __name__ == '__main__':
> from wxPython.wx import *
> import time
>
> class Canvas(wxWindow):
> def __init__(self, parent, id = -1, size = wxDefaultSize):
> wxWindow.__init__(self, parent, id, wxPoint(0, 0), size,
> wxSUNKEN_BORDER | wxWANTS_CHARS)
>
> self.point_count = 30000
> self.calc_points()
> EVT_PAINT(self, self.OnPaint)
> EVT_SIZE(self, self.OnSize)
>
> def calc_points(self):
> w,h = self.GetSizeTuple()
> from RandomArray import *
> x = arange(0., w, float(w)/self.point_count)
> y = randint(0., h, len(x))
> self.points = concatenate((x[:,NewAxis],y[:,NewAxis]),-1)
>
> def OnSize(self,event):
> self.calc_points()
> self.Refresh()
>
> def OnPaint(self,event):
> print len(self.points)
> dc = wxPaintDC(self)
> dc.SetPen(wxRED_PEN)
> dc.BeginDrawing()
>
> t1 = time.clock()
> dc.DrawLines(self.points)
> t2 = time.clock()
> print 'wxPython DrawLines:', t2-t1
>
> """
> # This first call is slow because your either compiling (very slow)
> # or loading a DLL (kinda slow)
> # Resize the window to get a more realistic timing.
> t1 = time.clock()
> dc.SetPen(wxGREEN_PEN)
> polyline(dc,self.points)
> t2 = time.clock()
> print 'Chunked calls to Polyline:', t2-t1
> """
> dc.EndDrawing()
>
> class CanvasWindow(wxFrame):
> def __init__(self, id=-1, title='Canvas',size=(500,500)):
> parent = NULL
> wxFrame.__init__(self, parent,id,title, size=size)
> self.canvas = Canvas(self)
> self.Show(1)
>
> class MyApp(wxApp):
> def OnInit(self):
> frame = CanvasWindow(title="Speed Examples",size=(500,500))
> frame.Show(true)
> return true
>
> app = MyApp(0)
> app.MainLoop()
>
>
>
>
>
> _______________________________________________
> wxpython-users mailing list
> wxpython-users@[...].org
> http://lists.wxwindows.org/mailman/listinfo/wxpython-users
--
Bryan Cole
Teraview Ltd., 302-304 Cambridge Science Park, Milton Road, Cambridge
CB4 0WG, United Kingdom.
tel: +44 (1223) 435380 / 435386 (direct-dial) fax: +44 (1223) 435382
_______________________________________________
wxpython-users mailing list
wxpython-users@[...].org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users
Thread:
eric
eric
Robin Dunn
bryan cole
bryan cole
eric
Robin Dunn
bryan cole
|