artist.py

I've been profiling some of my code which builds many

    > somewhat complex graphs. I've noticed that it spends almost
    > all it's time in the __init__ of the artist class. The time
    > there is almost entirely spent on calling identity_transform
    > which builds a SeperableTransform that does no
    > transforming--from what I can tell--which is consistent with
    > the name. The identity transform function buid a bunch of
    > other objects all of which are the same each time. My
    > question is, does it really need to build all these objects
    > over and over again. Given that Artist's __init__ is called
    > by so many things wouldn't it be better to have some static
    > constants to define these default transformation functions?
    > Am I missing something subtle or would this be an
    > improvement?

I'm hesitant to make a single (shared) identity transform since
transforms are mutable. But since most objects to not use the
identity_transform but rather a custom one, we can create it
lazily. I've implemented these changes in svn. Each artist (as
before) has a _transform instance but now it defaults to None. Then
in get_transform

    def get_transform(self):
        'return the Transformation instance used by this artist'
        if self._transform is None:
            self._transform = identity_transform()
        return self._transform

The harder part was modifying all of the derived classes that were
using the _transform attr directly -- all these had to be ported to
use get_transform instead. The changes are documented in API_CHANGES.

See if it speeds up your code -- it didn't make an appreciable change
to backend_driver.

Note the artist constructor shouldn't be a bottleneck in your python
script. If it is, you are probably creating lots-o-artists and you
might be able to use a collection instead. Eg, if you are making
hundreds or thousands of calls to plot and creating a comparable
number of Line2D artists, use a LineCollection instead.

But if you are still experiencing a problem and the changes I made to
svn don't help (eg if you are creating lots of objects that do require
the default identity_transform), you can experiment with using a
single cached identity_transform. Something like

import matplotlib.artist

_cached_transform = matplotlib.artist.identity_transform()
def my_identity_transform():
    return _cached_transform
matplotlib.artist.identity_transform = my_identity_transform

# import the rest of mpl here

Hope this helps...

JDH

John Hunter wrote:

I'm hesitant to make a single (shared) identity transform since
transforms are mutable.

Couldn't you make one that was immutable (is that possible in Python)? Or even just have a convention that you don't mutate the identity transform (though it could be way to late for that now!), kind of like how we all no not to assign anything else to the name "None".

The harder part was modifying all of the derived classes that were
using the _transform attr directly -- all these had to be ported to
use get_transform instead.

This sounds like a job for properties! make _transform a property, and code that gets and sets it directly should still work. though People that were accessing an underscored name directly should expect this kind of problem.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...259...

John, Tom,

I don't understand how generation of the identity transform for each Artist instance could possibly be a significant overall slowdown; it should be very fast, and only a small part of the time required to actually do anything useful with an Artist instance. I am wondering whether this could be a problem with the profiler, not a genuine slowdown.

Eric

John Hunter wrote:

···

    > I've been profiling some of my code which builds many
    > somewhat complex graphs. I've noticed that it spends almost
    > all it's time in the __init__ of the artist class. The time
    > there is almost entirely spent on calling identity_transform
    > which builds a SeperableTransform that does no
    > transforming--from what I can tell--which is consistent with
    > the name. The identity transform function buid a bunch of
    > other objects all of which are the same each time. My
    > question is, does it really need to build all these objects
    > over and over again. Given that Artist's __init__ is called
    > by so many things wouldn't it be better to have some static
    > constants to define these default transformation functions?
    > Am I missing something subtle or would this be an
    > improvement?

I'm hesitant to make a single (shared) identity transform since
transforms are mutable. But since most objects to not use the
identity_transform but rather a custom one, we can create it
lazily. I've implemented these changes in svn. Each artist (as
before) has a _transform instance but now it defaults to None. Then
in get_transform

    def get_transform(self):
        'return the Transformation instance used by this artist'
        if self._transform is None:
            self._transform = identity_transform()
        return self._transform

The harder part was modifying all of the derived classes that were
using the _transform attr directly -- all these had to be ported to
use get_transform instead. The changes are documented in API_CHANGES.

See if it speeds up your code -- it didn't make an appreciable change
to backend_driver.

Note the artist constructor shouldn't be a bottleneck in your python
script. If it is, you are probably creating lots-o-artists and you
might be able to use a collection instead. Eg, if you are making
hundreds or thousands of calls to plot and creating a comparable
number of Line2D artists, use a LineCollection instead.

But if you are still experiencing a problem and the changes I made to
svn don't help (eg if you are creating lots of objects that do require
the default identity_transform), you can experiment with using a
single cached identity_transform. Something like

import matplotlib.artist

_cached_transform = matplotlib.artist.identity_transform()
def my_identity_transform():
    return _cached_transform
matplotlib.artist.identity_transform = my_identity_transform

# import the rest of mpl here

Hope this helps...

JDH

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users