-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
The plot function of the matplotlib 2 and 3 versions is much slower than 1.5.3 #12542
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I agree your script slows down for me. OTOH, initializing a figure in your setup doesn't exhibit this slow down. I'm not sure why this happens, but I'm not sure what your use case is. In general, I'd suggest not trying to use the state-based interface for the best performance... setup="""import matplotlib.pyplot as plt
a=[1,2]
fig = plt.figure()
"""
test="plt.plot(a, a, '-')"
import timeit
timeit.timeit(test,setup,number=1000)
timeit.timeit(test,setup,number=1000)
timeit.timeit(test,setup,number=1000)
timeit.timeit(test,setup,number=1000)
timeit.timeit(test,setup,number=1000)
timeit.timeit(test,setup,number=1000) |
More straightforward test, I think? import timeit
setup = """
import matplotlib.pyplot as plt
plt.close('all')
a = [1, 2]
"""
test = "plt.plot(a,a,'-')"
# Prime stuff
timeit.timeit(test, setup, number=10)
t1 = timeit.timeit(test, setup, number=1000)
t2 = timeit.timeit(test, setup, number=10000)
print(t1, t2, t2 / t1) with results:
The base time went up slightly, but the main point is that the ratio is much higher now for some reason. |
Ran an automated bisect with ratio=13 as good/bad threshold and it points to 9617dfe as the first bad commit
which I guess might make sense as automated margins would require iterating through all artists. |
Thanks for figuring this out.
We're hitting quadratic behavior here :/ |
If anyone wants a fun project, this looks like a good excuse to dig up #2188 / https://github.com/airspeed-velocity/asv - there are some older results at https://matplotlib.org/mpl-bench/ |
I'm still waiting for them to accept the PR to enable it on NumPy's bench system... |
A pretty generous speed up can be had by disabling autoscale and sticky edges before plotting, and then re-enabling them after: import matplotlib.pyplot as plt
a = [1, 2]
fig, ax = plt.subplots()
for _ in range(10000):
ax.plot(a, a, '-') $ time python ../mpl-tests/issue12542a.py
real 0m39.860s
user 0m38.035s
sys 0m0.186s vs. import matplotlib.pyplot as plt
a = [1, 2]
fig, ax = plt.subplots()
ax.autoscale(False)
ax.use_sticky_edges = False
for _ in range(10000):
ax.plot(a, a, '-')
ax.use_sticky_edges = True
ax.autoscale(True) $ time python ../mpl-tests/issue12542a.py
real 0m7.476s
user 0m5.423s
sys 0m0.168s |
See #12546 for a small improvement. |
If there's not margin to be added, we don't need sticky edges, but if autoscaling is off, we _also_ don't need the sticky edges. This saves a lot of time when plotting many artists, like in matplotlib#12542.
If there's no margin to be added, we don't need sticky edges, but if autoscaling is off, we _also_ don't need the sticky edges. This saves a lot of time when plotting many artists, like in matplotlib#12542.
Ooops, I see what the difference is now in the tests. Sorry for the noise. I think a todo here, asside from makig the autolim algorithm faster, is to have a Performance Tweaks page where we list potential performance blocks that will slow things down for folks who want to have thousands of artists, or a very responsive GUI. Off the top of my head:
No doubt there are more. |
Adding to the list (especially with respect to the actual topic here)
|
OK, interestingly, though we definitely would want to avoid autoscale being called too much, looking at a profiler, it's actually accumulating sticky edges that takes the most time (even with @anntzer's optimization there):
|
One can squeeze out another ~30%(!) or so by replacing the property access (artist.sticky_edges, sticky.x, sticky.y) by direct attribute/tuple access (artist._sticky_edges, sticky[0], sticky[1] (sticky is a namedtuple)), which I guess is a reasonable patch (with a comment explaining the performance implications) but really just a band-aid over a problematic design. |
Thank you everyone. I now realize that the root cause of the problem at least for my case. Now I'm trying to use the options: |
So is ti possible to delay If that is not possible, could we accumulate |
We can't delay it until draw time because of code that calls get_xlim/ylim
and such before calling plt.show().
…On Thu, Oct 18, 2018 at 1:05 PM Jody Klymak ***@***.***> wrote:
So is ti possible to delay autoscale_view to draw time? Seems a
straightforward solution.
If that is not possible, could we accumulate x_stickies and y_stickies in
add_artist and remove them in artist.remove? Unless I'm misunderstanding,
the problem is that making these lists from scratch every time a new artist
is added is inefficient.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#12542 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AARy-FmXamwU4WTmq9Wg_yTq7pcUOn9Zks5umLTzgaJpZM4XjGjG>
.
|
If we cache the sticky-ness, we need to track if it is updated on the artists. |
Bug report
Bug summary
The plot function of the matplotlib 2 and 3 versions is much slower than the plot function of matplotlib 1.5.3 if one plots many lines (and other objects) in an Axes.
Code for reproduction
I have tested it on an Ubuntu server (CLI only), version 16.04 with python 3.5.2 (through virtualenv), matplotlib 1.5.3 with backend agg set by matplotlibrc.
=> around 0.6-0.7 sec, it is stable for a few dozen times.
On the same machine & operating system, python 3.5.2 (through virtualenv), matplotlib 2.2.2 with backend agg.
=> getting slower and slower...
Note that matplotlib 2.0.0, 2.0.1, 2.1.0, 2.1.2, 2.2.2, or 3.0.0 has the same slowdown behavior. If I set svg as backend, the result is the same as agg (I confirmed backend="svg" only for matplotlib 2.0.0 on the Ubuntu server).
This behavior is also confirmed on a Windows distribution: WinPython-64bit-3.4.4.6Qt5 with matplotlib 2.0.0 and default backend TkAgg, but not for WinPython-64bit-3.4.4.5Qt5 with matplotlib version 1.5.3 and TkAgg, though the situation is much more complex. In addition, WinPython-64bit-3.5.1.1 and matplotlib 2.1.0 (packaged by Christoph Gohlke) causes the same slowdown behavior.
Another windows distribution anaconda 3 version 4.4.0(64bit) also has a similar behavior. For the anaconda 3 environment, all the packages are default of the 4.4.0 distribution (python 3.6 and matplotlib 2.0.2 with backend qt5agg), and it runs on windows7-x64.
If I close the figure by pyplot.close(), the slowed plot() is returned to the initial state.
Expected outcome
The expected outcome is "no slowdown for the plot function of matplotlib 3" as the matplotlib version 1.5.3.
Matplotlib version
print(matplotlib.get_backend())
): aggOther note
I have used a script to write huge maps with overlayed many lines drawn by plot(). When I'm with matplotlib 1.5.3, it takes several minutes to output a bunch of png files, but no fatal problem is there. However, with 2.0.0-3.0.0 it takes several hours or more, and I cannot use the script at all.
I believe this slowdown behavior can occur for most of the matplotlib environments. I think this is not an OS/system dependent bug/specification.
The text was updated successfully, but these errors were encountered: