[wxPython] DrawLines and a bunch points

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()

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>

I always get between 0.25 and 0.60, depending on how much area needs
refreshed.

    2. Does anyone have any insight into what is going on here?

Not really. There is some (probably) unnecessary overhead there though.
wxPython's DrawLines transforms the sequence into an array of wxPoint
objects and then calls the C++ DrawLines. (On MSW the wxPoint object is the
same structure as MSW's POINT so another transform to call Polyline is not
needed.)

         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.

No idea.

    3. Does Linux have the same problem?

I don't have Numeric installed there, so I don't know.

    4. Am I missing an extra call somewhere that would fix all my
        problems?

We added DrawLineList to wxPython's DC in 2.3.2 or .1 that doesn't have the
transformation overhead described above. It takes a sequence of
(x1,y1,x2,y2) sequences, and optionally a list of pens, and iterates through
it calling DrawLine. You end up with a ton more win32 API calls, but no
transformation.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

I've found what appeared to be a local problem on my windows system
drawing a 50,000 segment polyline to a wxMemoryDC. I was using the
wxDC::Drawlines() function. On Linux the drawing was always fast and
always reproducible. On my windows system, things looked fine provided
the wxPEN had WIDTH=1. As soon as I set the pen width to 2 or more,
everything went pearshaped; the drawing slowed by > 2 orders of
magnitude for <2000 points. For more than 5000 points, the programs
crashed entirely.

I posted a test script a while back (25th Feb 2002) and other users
reported no problems on their WinNT system (I was using win98), so I
think it might be a bug in my graphics-card driver, or the card itself
(I guessing here!).

I can't test your script as I don't have weave installed. If you post a
non-weave version, I'll happily test it on linux.

Bryan

···

On Tue, 2002-04-30 at 05:06, Robin Dunn wrote:

>
> 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>

I always get between 0.25 and 0.60, depending on how much area needs
refreshed.

> 2. Does anyone have any insight into what is going on here?
>

Not really. There is some (probably) unnecessary overhead there though.
wxPython's DrawLines transforms the sequence into an array of wxPoint
objects and then calls the C++ DrawLines. (On MSW the wxPoint object is the
same structure as MSW's POINT so another transform to call Polyline is not
needed.)

> 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.

No idea.

>
> 3. Does Linux have the same problem?

I don't have Numeric installed there, so I don't know.

>
> 4. Am I missing an extra call somewhere that would fix all my
> problems?

We added DrawLineList to wxPython's DC in 2.3.2 or .1 that doesn't have the
transformation overhead described above. It takes a sequence of
(x1,y1,x2,y2) sequences, and optionally a list of pens, and iterates through
it calling DrawLine. You end up with a ton more win32 API calls, but no
transformation.

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.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

>
> 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>

I always get between 0.25 and 0.60, depending on how much area needs
refreshed.

Thanks for the test. It sounds like an idiosyncrasy of my machine. I guess
that is better news than the alternative...

> 2. Does anyone have any insight into what is going on here?
>

Not really. There is some (probably) unnecessary overhead there though.
wxPython's DrawLines transforms the sequence into an array of wxPoint
objects and then calls the C++ DrawLines. (On MSW the wxPoint object is the
same structure as MSW's POINT so another transform to call Polyline is not
needed.)

Right. Well, for now, the extra overhead is a minor issue compared to the
PolyLine problem. weave provides a way around the extra overhead in the final
tweaking stages, but, for now, I'm more interested in just getting the project
working with reasonable performance.

> 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.

No idea.

Dag. Me neither.

>
> 3. Does Linux have the same problem?

I don't have Numeric installed there, so I don't know.

>
> 4. Am I missing an extra call somewhere that would fix all my
> problems?

We added DrawLineList to wxPython's DC in 2.3.2 or .1 that doesn't have the
transformation overhead described above. It takes a sequence of
(x1,y1,x2,y2) sequences, and optionally a list of pens, and iterates through
it calling DrawLine. You end up with a ton more win32 API calls, but no
transformation.

It doesn't sound like this is as good of a solution for drawing an array of
points. I'll stick with DrawLines.

thanks for your help,
eric

···

----- Original Message -----
From: "Robin Dunn" <robin@alldunn.com>
To: <wxpython-users@lists.wxwindows.org>
Sent: Tuesday, April 30, 2002 12:06 AM
Subject: 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@lists.wxwindows.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

Hey Bryan,

Thanks. It is interesting to see that it is faster on on your machine with the
wxPython overhead than it is, even with my hack, on a faster windows machine 850
MHz.

Anyway, I think there is something strange on my machine. I'll look into it
further.

thanks for the benchmarks.

eric

···

----- Original Message -----
From: "bryan cole" <bryan.cole@teraview.co.uk>
To: <wxpython-users@lists.wxwindows.org>
Sent: Wednesday, May 01, 2002 4:21 AM
Subject: 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@lists.wxwindows.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@lists.wxwindows.org
http://lists.wxwindows.org/mailman/listinfo/wxpython-users

Thanks. It is interesting to see that it is faster on on your machine

with the

wxPython overhead than it is, even with my hack, on a faster windows

machine 850

MHz.

That's because it is only measuring the time it takes to send the commands
to the X-Server, not the time it takes for the X-Server to do the drawing.

···

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

That's correct. The real rendering time by the X-server is approx. 0.5
sec (estimated by watching the screen).

Bryan

···

On Wed, 2002-05-01 at 19:42, Robin Dunn wrote:

>
> Thanks. It is interesting to see that it is faster on on your machine
with the
> wxPython overhead than it is, even with my hack, on a faster windows
machine 850
> MHz.

That's because it is only measuring the time it takes to send the commands
to the X-Server, not the time it takes for the X-Server to do the drawing.

--
Robin Dunn
Software Craftsman
robin@AllDunn.com Java give you jitters?
http://wxPython.org Relax with wxPython!

_______________________________________________
wxpython-users mailing list
wxpython-users@lists.wxwindows.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