RE : Re: Speed of dynamic_image

So it seems my optimisation has an impact, although

    > moderate... On the other hand, the copy mechanism induce
    > some lag in the TkAgg backend, while reusing the buffer
    > in FltkAgg seems a nice improvement...To check that, I
    > disabled the copy in the TkAgg (tkagg.blit call), and got
    > 16.4 FPS). I think thus my FltkAgg backend has the same
    > speed as bare Agg, while some optim are maybe possible on
    > TkAgg (if Tk can reuse an extern buffer, I am a complete
    > beginner in Tk so maybe my conclusion are invalid, if
    > there is a flaw in my examples...

I didn't see where the optimization was helping - could you clarify?
It looks like about a 5% for tkagg and there are no comparisons for
the fltkagg with "classic vs optimized"

  Classic TkAgg: 9.98 FPS
  Improved TkAgg: 10.6 FPS
  FltkAgg: 16.7 FPS

As you may know, blitting in tk is pretty slow and there doesn't
appear to be anything we can do about it short of some platform
dependent extension code (which might be worth doing at some point for
linux and win32). With your example I get approx 14 FPS with tkagg on
my system and 45 FPS with gtkagg. My point is that unless there are
some fundamental limitations in fltk as there are in tk, you might
want to look to gtkagg as a performance benchmark rather than tkagg.
gtkagg is typically 3x faster than tkagg for dynamic plots.

    > Depending on what you think of that, I can submit patches
    > for the Agg optimisation, exposing the Agg buffer as a
    > python buffer object (allowing buffer sharing instead of
    > buffer copying, if toolkit support this). For the fltk
    > backend, I am ready to support it but it should wait
    > acceptance of some modif I made in the python bindings of
    > fltk, for now it does not work with stock pyfltk
    > bindings...

Please send them in, either to the list or directly to Todd and
myself. Todd will be interested in anything pertaining to tkagg. I
understand the rational behind not creating a new agg buffer object
with each draw, but at the same time your numbers seem to suggest that
it isn't too important, performance wise. Also, I am not sure about
the necessity of creating a python buffer object - perhaps you can
explain this a bit more. tkagg and gtkagg both use the agg rendering
buffer directly with no string copy, eg

  RendererAgg* aggRenderer = static_cast<RendererAgg*>(args[1].ptr());

//gtk

    gdk_draw_rgb_32_image(drawable, gc, 0, 0,
        width,
        height,
        GDK_RGB_DITHER_NORMAL,
        aggRenderer->pixBuffer,
        width*4);
// tk
    block.pixelPtr = aggRenderer->pixBuffer;

where pixBuffer is the agg pixel buffer.

What does exposing the buffer in the python layer buy you?

It is best (for me) for you to submit your changes as complete files
so I can merge / compare with ediff; my dev tree is often out of sync
with the non-devel cvs tree so applying diffs is hard.

Thanks!
JDH

I didn't see where the optimization was helping - could you
clarify? It looks like about a 5% for tkagg and there are no
comparisons for the fltkagg with "classic vs optimized"

  Classic TkAgg: 9.98 FPS
  Improved TkAgg: 10.6 FPS
  FltkAgg: 16.7 FPS

I will check the non optimized (ie with no reuse of Agg buffers) FltkAgg
backend tomorrow, but you are right, the improvement are reproductible
but small. The change for reusing buffer is trivial though, and it may
help if there is memory leak...

As you may know, blitting in tk is pretty slow and there
doesn't appear to be anything we can do about it short of
some platform dependent extension code (which might be worth
doing at some point for linux and win32). With your example
I get approx 14 FPS with tkagg on my system and 45 FPS with
gtkagg. My point is that unless there are some fundamental
limitations in fltk as there are in tk, you might want to
look to gtkagg as a performance benchmark rather than tkagg.
gtkagg is typically 3x faster than tkagg for dynamic plots.

You are right, I should definitely install pygtk on my system to check
that, I wonder how a 3X increase in FPS is possible: after all,
de-activating blit in the TkAgg produce only a 1.5X increase (and no
image of course :wink: ): something else than Agg must hold Tk (and Fltk)
back then: I have to test the FPS one have without Agg drawing and
blitting, only canvas update, with GTK, Tk and Fltk, to be sure...

Please send them in, either to the list or directly to Todd
and myself. Todd will be interested in anything pertaining
to tkagg.

Ok, I send the complete relevant files as attachement tomorrow, to you
and Todd.

I understand the rational behind not creating a
new agg buffer object with each draw, but at the same time
your numbers seem to suggest that it isn't too important,
performance wise.

It could be more important for GTKAgg, if it is closer to raw Agg speed
than TkAgg and FltkAgg...Something to test would be to use the Agg
backend without exporting the pixmap buffer but doing the drawing, and
check how many draw/second one can have on the examples, to really check
the penalty associated to the different toolkits, and the maximum gain
we can have by reusing Agg buffer instead of creating one for each
draw...Is this doable?

Also, I am not sure about the necessity of
creating a python buffer object - perhaps you can explain
this a bit more. tkagg and gtkagg both use the agg rendering
buffer directly with no string copy, eg

  RendererAgg* aggRenderer = static_cast<RendererAgg*>(args[1].ptr());

//gtk

    gdk_draw_rgb_32_image(drawable, gc, 0, 0,
        width,
        height,
        GDK_RGB_DITHER_NORMAL,
        aggRenderer->pixBuffer,
        width*4);
// tk
    block.pixelPtr = aggRenderer->pixBuffer;

where pixBuffer is the agg pixel buffer.

What does exposing the buffer in the python layer buy you?

In these cases nothing performance wise, in fact the way you use should
me marginally faster (avoiding the creation/destruction of python buffer
objects ).
Python buffer objects is a way for me to implement the transfer without
copy of the Agg buffer to fltk in more "abstract" way: no need to
implement a c extension that know both the internals of agg and fltk, I
split it using the python buffer as a standard protocol (buffer objects
were intended for just this use, I think...).
This is not very important, but it could simplify things if there is
multiple renderer and multiple toolkits to bind...like if alternative to
Agg is implemented (or multiple version of Agg must be supported)...and
I guess that the overhead of this creation/destruction of python buffer
objects is really negligeable.

Best regards,

Greg.

You are right, I should definitely install pygtk on my system to check
that, I wonder how a 3X increase in FPS is possible: after all,
de-activating blit in the TkAgg produce only a 1.5X increase (and no
image of course :wink: ): something else than Agg must hold Tk (and Fltk)
back then: I have to test the FPS one have without Agg drawing and
blitting, only canvas update, with GTK, Tk and Fltk, to be sure...

I guess I'm surprised at that. How are you disabling the blit?
If no blit is being done, where else is the time going if not
for agg?

Puzzled, Perry

Though I suppose it may simply be in the mechanism that
tk uses to update it's own buffer (it does its own blitting
behind the scenes as I understand it)...

> You are right, I should definitely install pygtk on my
system to check
> that, I wonder how a 3X increase in FPS is possible: after all,
> de-activating blit in the TkAgg produce only a 1.5X
increase (and no
> image of course :wink: ): something else than Agg must hold Tk
(and Fltk)
> back then: I have to test the FPS one have without Agg drawing and
> blitting, only canvas update, with GTK, Tk and Fltk, to be sure...
>
I guess I'm surprised at that. How are you disabling the
blit? If no blit is being done, where else is the time going
if not for agg?

In the draw method of the FigureCanvasTkAgg class (in
matplotlib/backends/backend_tkagg.py file), I just commented out the
second line, going from:

def draw(self):
        FigureCanvasAgg.draw(self)
        tkagg.blit(self._tkphoto, self.renderer._renderer, 2)
        self._master.update_idletasks()

To:

def draw(self):
        FigureCanvasAgg.draw(self)
        #tkagg.blit(self._tkphoto, self.renderer._renderer, 2)
        self._master.update_idletasks()

This makes the image dissapear from screen of course, but still draw the
image in the in-memory Agg buffer...and ask the Tk canvas to redraw
itself (allways with the same empty image), I guess...so I indeed
suspect that the Tk canvas updating is causing the slow down somehow...I
will check that tomorrow for sure!

Greg, puzzled too :wink:

I just checked (after spending all day solving network problem :-() what
effect the re-use of Agg buffer optimisation has on FltkAgg backend:

    Classic TkAgg: 9.98 FPS
    Improved TkAgg: 9.98 FPS
    classic FltkAgg: 16.1 FPS
    Improved FltkAgg: 17.2 FPS

I also installed pyGtk to be able to test the framerate I gor on may
computer:
     Classic GTKAgg: 16 FPS
     Modified GTKAgg (avoid switch backend, which make my re-use of agg
buffer impossible, use multiple inheritance instead): 16 FPS
     Improved modified GTKAgg: 16.8 FPS

And finaly, to have a complete picture, I tried Tk without blitting (as
explained in a previous message)
  classic TkAgg without blit: 14.3 FPS
  improved TkAgg without blit: 16 FPS

There is various strange things in these benchmarks:
first I was not able to reproduce the (very small but reproductible)
advantage I observed yesterday for Agg buffer re-use optimization in the
TkAgg backend...It is observable in the FltkAgg and TkAgg backend,
though...and even more so in the TkAgg without blitting one...Maybe this
is maked by the blitting time in the normal TkAgg, though, so this does
not disturb me too much...
Next, I do not observe the high performance of the GTKAgg backend here,
on the contrary the FPS it gives me are in line with the Fltk ones, and
even with Tk when we get rid of the slow blitting...This is quite
surprising...

On the other hand, I have less trouble understanding these results than
the higher GTKAgg performance you report, so to be really complete I
tried an bare Agg rendering:
Just use the same example as my light dynamic plot (mode animation), but
with a matplotlib.use("Agg") and a
while True:
   updatefig()

loop instead of idle callback...
Here are the timings:
Classic Agg: 19 FPS (or, better said, RenderingPerSecond)
Optimized Agg: 20.55 RPS

So this confirm what I have observed on the various *Agg backends, which
in summary would be:
-Optimization of Agg, to reuse buffer if possible: Gain from 8% to 0%,
depending on the backend (max on Agg, small to non existent on TkAgg).
It depends also on the complexity of the rendering, the gain will be
higher when simple drawings are done, and minimal when very complex
figures are drawn...This could help for memory leak maybe, though...and
as you will see is a very minimal hack...

Performance of the various *Agg backends, using Agg as reference and a
very simple dynamic plot (for the new reuse Agg buffer scheme, current
"new Agg every draw" should be very similar):
TkAgg: 49% (ouch!)
TkAgg without blit: 78%
GTKAgg: 82%
FltkAgg: 84%

So Fltk and GTK are fast (the 20 % overhead is due to transfer to screen
buffer, double buffering, and callbacks/idle mechanisms, I guess, no way
to get better than that)
TkInter is a slower toolkit, mainly cause of blit, and also for other
reasons it seems.

Only remaining mystery (but it is a big one!) is why you observe very
different things for GTKAgg? Is it a GTK version problem? A compilation
option? This is really surprising, given the bare Agg test give me RPS
in line with my FPS...Only thing I can think of is a option during Agg
compile that decrease the performance of my Agg somehow...

You will find included a tar.gz of all the files I modified (including
small examples and my FltkAgg backend - even if it is not too usefull
before pyfltk has been updated)...If you need any more information or
want to discuss this, I would be glad to help :slight_smile:

PS: I forward this to matplotlib-devel, without the attachment: I do not
know if the mailinglist would accept such a thing...