-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
[Bug]: Savefig slow with subplots #26150
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 am curious about why you use both I did enjoy the video 😁 |
@rcomer because this is Matplotlib: You have to do redundant things at least twice! :-) Seriously though, I don't think they're doing the exact same thing - at least when you're having many sub-plots, where But maybe you're right that I could perhaps omit Also note that |
You can have two of fast, simple, and robust. simple and robust: constrained layout; fast and simple: manually placing the axes; fast and robust: come up with your own heuristics for when an axes needs to be resized. In your case I'd go for fast and simple and hardcode the axes locations using subplotpars or manually. Note that by calling the only time bbox_inches='tight' may be useful is if your axes have a set aspect ratio or if you have things like a manually placed suptitle that are not part of the subplot layout. But you should just use constrained layout instead. I'm going to close this, and suggest discussion at https://discourse.matplotlib.org as I don't think there are any bugs per-se here. |
It is odd that sharex takes longer. |
Well maybe I closed too soon. It's possible the sharing code is going down a rabbit hole with so many axes. |
Let's reopen for the sharex issue. That does make things slower and I'm not sure why. I suspect some cross checking of bounds that is cascading each plot call. |
@jklymak Thanks for the quick and detailed reply! I don't think I can call
I use The problem I am having with setting So I really need a way to adjust the sub-plots automatically, to make the layout look nice and tight without too much white-space everywhere. PS: I don't consider this to be a 'bug' per-se either, but there was no option to open this as a performance issue. |
|
@rcomer thanks! I have updated the table above with time-usage for these. They're just as slow as |
My hunch of where to check is to see how many times we check |
#26899 seems to help with this. Using %%timeit
stream = BytesIO()
fig_many.savefig(stream, format='svg', bbox_inches='tight')
s = stream.getvalue() With Using %%timeit
stream = BytesIO()
fig_many_sharex.savefig(stream, format='svg', bbox_inches='tight')
s = stream.getvalue() with |
I believe I have understood why sharex is slower. When the x-axis is shared across the columns, the xtick labels are removed from all but the last row. So, for all but the last row, when we call If we add a line in the ax.xaxis.set_ticks_position("top") then So I think it would be good to change how |
This was kept open for the question of why sharex caused So I think this is now done. Please comment and/or re-open if you disagree. |
Bug summary
There are apparently 3 problems which combine to make savefig slow: (1) The use of many sub-plots, (2) the use of
bbox_inches='tight'
, and (3) the use ofsharex='columns'
. Unfortunately I need to use all three.Code for reproduction
Actual outcome
The test-results are summarized in this table, which are all for the SVG format. A few tests are made above for JPG and PNG formats and the results are similar.
fig_single
fig_many
fig_many_sharex
Edit: Added time-usage for setting either
layout='constrained'
or'tight'
when creating theFigure
objects.Expected outcome
I would like it to run like this (you asked for a visual example).
Additional information
Thanks for making Matplotlib, I've been using it for many open-source projects in the past!
I am currently building a web-app where Matplotlib will be generating many SVG plots on a server that is running in the cloud. My own functions for generating the data are very fast, but unfortunately the plotting itself is very slow. For example, a figure with 3 columns and 10 rows of sub-plots takes 7 seconds to run
savefig
- even though most of the sub-plots only have a simple text-string such as "Same as previous", and the few other sub-plots are either line-plots orfill_between
that are generated from just 100 data-points each.I have tried simulating this problem in the sample code above, where
fig_many
has many sub-plots, andfig_single
has a single plot with the same total number of data-points. I also tried using a profiler on this code, but it would take me forever to try and understand what the problem is in Matplotlib's code, and whether it's even fixable.Please tell me if it might be possible to improve the speed, or if it's not possible then please explain the technical reason, and whether there is a work-around.
Thanks!
Operating system
Kubuntu 22
Matplotlib Version
3.7.1
Matplotlib Backend
module://matplotlib_inline.backend_inline
Python version
3.9.12
Jupyter version
6.4.12 (through VSCode)
Installation
pip
The text was updated successfully, but these errors were encountered: