| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Thanks for the PR. The speedup is impressive, and the added complexity (rc caching) is bearable.
Strategically, I would like to move away from single-tick handling, but in the mean time this is a reasonable improvement.
Sorry, something went wrong.
Having tick collections is indeed the way to go. This change is orthogonal as it avoids some tick operations altogether. (but maybe if ticks are really fast that would not matter) |
Sorry, something went wrong.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Thanks, this is a substantial and concise improvement now!
Sorry, something went wrong.
Thanks for reviews! This was (and still is) tricky to get right. If you have more suggestions (in particular for additional tests) let me know |
Sorry, something went wrong.
|
Can confirm the speedup, pretty impressive IMO! Circled bits are removed from this profiling using your clf script. |
Sorry, something went wrong.
|
I think this causes an issue for cartopy (SciTools/cartopy#2674) |
Sorry, something went wrong.
|
@mathause Thanks for reporting. I have a branch with a potential fix (unverified yet). Could you check whether that works? main...eendebakpt:matplotlib:fix/clear-custom-spine-type |
Sorry, something went wrong.
|
[Picking up my Cartopy hat] Thanks for catching that @mathause and for the quick fix @eendebakpt. I confirm I reproduced the error in the Cartopy tests, and that the tests pass with the new branch. |
Sorry, something went wrong.
PR #31525 made Axes.__clear call Spine._ensure_transform_is_set on every spine, which calls set_position(('outward', 0.0)) for a spine that still carries the placeholder transform from Spine.__init__. Custom spines such as cartopy's GeoSpine have a non-cartesian spine_type, manage their own transform, and may reject set_position, so this raised NotImplementedError on plain subplot creation. Restrict the spine nudge to the four standard cartesian spine types, the only ones set_position / get_spine_transform support. See SciTools/cartopy#2674. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| Back | FazBrowse Home | New Git URL |
PR summary
The performance if matplotlibs ticks is a bottleneck in various plots. See for example the discussions and references in #5665, #31012, #29594.
In this PR we prevent materialization of the _LazyTickList when there are no ticks created yet. With the tick-materialization cascade gone from Axes.__clear, the spine transforms the cascade used to install as a side effect are installed explicitly at the end of __clear.
Benchmark results (updated):
# /// script # requires-python = ">=3.10" # dependencies = ['matplotlib', 'numpy', 'pyperf'] # /// """pyperf micro-benchmarks for matplotlib axis/tick init+clear cost. """ import pyperf setup = """ import matplotlib matplotlib.use("Agg") # matplotlib.use("QtAgg") # snap/glibc mismatch; use offscreen: # import os; os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") import numpy as np import matplotlib.pyplot as plt GRID = 8 rng = np.random.default_rng(0) x1000 = np.arange(1000) y1000 = rng.standard_normal(1000) # Pre-create reusable figure for clear_grid / reuse_axes cases. _fig_clear = plt.figure() _fig_grid, _axs_grid = plt.subplots(GRID, GRID) _axs_flat = _axs_grid.ravel() # Warmup — first call pays font-cache / backend-init costs. plt.close(plt.subplots(GRID, GRID)[0]) """ runner = pyperf.Runner() # Fresh figure each iter — full Axes.__init__ cost for an 8x8 grid. runner.timeit( name="init_grid 8x8", stmt="fig, axs = plt.subplots(GRID, GRID); plt.close(fig)", setup=setup, ) # Reuse one Figure, clear + re-populate with an 8x8 grid. runner.timeit( name="clear_grid 8x8", stmt="_fig_clear.clear(); _fig_clear.subplots(GRID, GRID)", setup=setup, ) # Iterate ax.clear() across an existing 8x8 grid. runner.timeit( name="reuse_axes 8x8", stmt="[ax.clear() for ax in _axs_flat]", setup=setup, ) # Figure num=100: clear + plot 1000-point line + legend. Reuses the same # numbered figure across iterations so only clear+plot+legend is measured. runner.timeit( name="fig100 clear+plot1000+legend", stmt=( "fig = plt.figure(num=100);" " fig.clear();" " ax = fig.add_subplot();" " ax.plot(x1000, y1000, label='y');" " ax.legend()" ), setup=setup, )Closes #23771.
AI Disclosure
Claude was used in identifying performance bottlenecks related to tick creation. Initially the goal was to create tick collections (as described in one of the references), but this approach seems to be a small change with large impact.
PR checklist