updating an image with a colorbar, performance issues

I have been working on an application which is basically a dressed up version
of embedding_in_qt4.py. I have two canvases, one is just a plot, the other an
image with a colorbar, both of which should get updated about once a second
as data is acquired. I noticed that for larger images, it was taking longer
to update the canvases as time went on.

Attached is a script that demonstrates the problem (png's are also attached
for those who dont have PyQt4). At each timeout, I check the time, generate a
new random array, update the image's data, draw it, collect garbage, and
check the time again. The plot in the upper window shows how long it took to
update the image canvas as a function of iteration number.

When the image has a colorbar, the time to update the image canvas increases
linearly, about 0.3 ms/iteration. This can really add up: after 20,000
iterations it takes about 5-6 seconds to update the image canvas. If I
comment out the line that creates the colorbar (line 64), the time to update
the image canvas does not increase.

A couple other observations and benchmarks from this test:

* The intercept for the update time with a color bar was 0.17 seconds
* With the colorbar enabled but garbage collection turned off, the application
slowly consumed memory, roughly 12KB/iteration
* Updating an image without a colorbar took 0.1 seconds per iteration, and did
not increase
* Turning off both garbage collection and the colorbar decreased the update
time to 0.043 seconds, with maybe 1.7 KB/iteration increase in memory usage.

I don't know if I'll get a chance to dig any further into this in the next two
weeks. For now, I'll just disable the colorbar in my application.

Darren

with_colorbar.png

without_colorbar.png

slow_test.py (4.32 KB)

I should have some time today to look at this, unless any other developers already know an obvious solution.

Cheers,
Mike

Darren Dale wrote:

···

I have been working on an application which is basically a dressed up version of embedding_in_qt4.py. I have two canvases, one is just a plot, the other an image with a colorbar, both of which should get updated about once a second as data is acquired. I noticed that for larger images, it was taking longer to update the canvases as time went on.

Attached is a script that demonstrates the problem (png's are also attached for those who dont have PyQt4). At each timeout, I check the time, generate a new random array, update the image's data, draw it, collect garbage, and check the time again. The plot in the upper window shows how long it took to update the image canvas as a function of iteration number.

When the image has a colorbar, the time to update the image canvas increases linearly, about 0.3 ms/iteration. This can really add up: after 20,000 iterations it takes about 5-6 seconds to update the image canvas. If I comment out the line that creates the colorbar (line 64), the time to update the image canvas does not increase.

A couple other observations and benchmarks from this test:

* The intercept for the update time with a color bar was 0.17 seconds
* With the colorbar enabled but garbage collection turned off, the application slowly consumed memory, roughly 12KB/iteration
* Updating an image without a colorbar took 0.1 seconds per iteration, and did not increase
* Turning off both garbage collection and the colorbar decreased the update time to 0.043 seconds, with maybe 1.7 KB/iteration increase in memory usage.

I don't know if I'll get a chance to dig any further into this in the next two weeks. For now, I'll just disable the colorbar in my application.

Darren

------------------------------------------------------------------------

------------------------------------------------------------------------

------------------------------------------------------------------------

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

------------------------------------------------------------------------

_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

It seems that the set of callbacks held by the Axis objects was not being cleared by cla().

This has been fixed in SVN r4404, and does seem to correct your example script. I'd appreciate a sanity check by the other developers to make sure that change makes sense -- i.e. that the Axis callbacks don't really need to stick around beyond the call to cla() for any reason I'm not aware of.

An alternative and more general solution would be to change the implementation of CallbackRegistry so it uses a WeakValueDictionary, so that it won't keep callback targets alive that have otherwise been orphaned. But I can't decide whether that is a good thing or would just hide easily fixed errors.

Cheers,
Mike

Michael Droettboom wrote:

···

I should have some time today to look at this, unless any other developers already know an obvious solution.

Cheers,
Mike

Darren Dale wrote:

I have been working on an application which is basically a dressed up version of embedding_in_qt4.py. I have two canvases, one is just a plot, the other an image with a colorbar, both of which should get updated about once a second as data is acquired. I noticed that for larger images, it was taking longer to update the canvases as time went on.

Attached is a script that demonstrates the problem (png's are also attached for those who dont have PyQt4). At each timeout, I check the time, generate a new random array, update the image's data, draw it, collect garbage, and check the time again. The plot in the upper window shows how long it took to update the image canvas as a function of iteration number.

When the image has a colorbar, the time to update the image canvas increases linearly, about 0.3 ms/iteration. This can really add up: after 20,000 iterations it takes about 5-6 seconds to update the image canvas. If I comment out the line that creates the colorbar (line 64), the time to update the image canvas does not increase.

A couple other observations and benchmarks from this test:

* The intercept for the update time with a color bar was 0.17 seconds
* With the colorbar enabled but garbage collection turned off, the application slowly consumed memory, roughly 12KB/iteration
* Updating an image without a colorbar took 0.1 seconds per iteration, and did not increase
* Turning off both garbage collection and the colorbar decreased the update time to 0.043 seconds, with maybe 1.7 KB/iteration increase in memory usage.

I don't know if I'll get a chance to dig any further into this in the next two weeks. For now, I'll just disable the colorbar in my application.

Darren

------------------------------------------------------------------------

------------------------------------------------------------------------

------------------------------------------------------------------------

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/

------------------------------------------------------------------------

_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
matplotlib-devel List Signup and Options

--
Michael Droettboom
Science Software Branch
Operations and Engineering Division
Space Telescope Science Institute
Operated by AURA for NASA

Thank you for tracking this down, Mike.

Darren

···

On Wednesday 21 November 2007 11:17:04 am Michael Droettboom wrote:

It seems that the set of callbacks held by the Axis objects was not
being cleared by cla().

This has been fixed in SVN r4404, and does seem to correct your example
script. I'd appreciate a sanity check by the other developers to make
sure that change makes sense -- i.e. that the Axis callbacks don't
really need to stick around beyond the call to cla() for any reason I'm
not aware of.

An alternative and more general solution would be to change the
implementation of CallbackRegistry so it uses a WeakValueDictionary, so
that it won't keep callback targets alive that have otherwise been
orphaned. But I can't decide whether that is a good thing or would just
hide easily fixed errors.

Cheers,
Mike

Michael Droettboom wrote:
> I should have some time today to look at this, unless any other
> developers already know an obvious solution.
>
> Cheers,
> Mike
>
> Darren Dale wrote:
>> I have been working on an application which is basically a dressed up
>> version of embedding_in_qt4.py. I have two canvases, one is just a plot,
>> the other an image with a colorbar, both of which should get updated
>> about once a second as data is acquired. I noticed that for larger
>> images, it was taking longer to update the canvases as time went on.
>>
>> Attached is a script that demonstrates the problem (png's are also
>> attached for those who dont have PyQt4). At each timeout, I check the
>> time, generate a new random array, update the image's data, draw it,
>> collect garbage, and check the time again. The plot in the upper window
>> shows how long it took to update the image canvas as a function of
>> iteration number.
>>
>> When the image has a colorbar, the time to update the image canvas
>> increases linearly, about 0.3 ms/iteration. This can really add up:
>> after 20,000 iterations it takes about 5-6 seconds to update the image
>> canvas. If I comment out the line that creates the colorbar (line 64),
>> the time to update the image canvas does not increase.
>>
>> A couple other observations and benchmarks from this test:
>>
>> * The intercept for the update time with a color bar was 0.17 seconds
>> * With the colorbar enabled but garbage collection turned off, the
>> application slowly consumed memory, roughly 12KB/iteration
>> * Updating an image without a colorbar took 0.1 seconds per iteration,
>> and did not increase
>> * Turning off both garbage collection and the colorbar decreased the
>> update time to 0.043 seconds, with maybe 1.7 KB/iteration increase in
>> memory usage.
>>
>> I don't know if I'll get a chance to dig any further into this in the
>> next two weeks. For now, I'll just disable the colorbar in my
>> application.
>>
>> Darren
>>
>>
>> ------------------------------------------------------------------------
>>
>>
>> ------------------------------------------------------------------------
>>
>>
>> ------------------------------------------------------------------------
>>
>> ------------------------------------------------------------------------
>>- This SF.net email is sponsored by: Microsoft
>> Defy all challenges. Microsoft(R) Visual Studio 2005.
>> http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
>>
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Matplotlib-devel mailing list
>> Matplotlib-devel@lists.sourceforge.net
>> matplotlib-devel List Signup and Options

--
Darren S. Dale, Ph.D.
dd55@...143...