Symptom
In a fresh environment, the first plot (or, before #198, plain import spatialmath) can take 10–20 s. Later runs on the same machine are fast, so the delay is hard to reproduce on a long-lived development machine, but it can recur on every run in containers or CI.
Cause
This is Matplotlib behaviour, not spatialmath code. The first time Matplotlib's font manager runs with no font cache, it scans every font installed on the system to build one. That's the "Matplotlib is building the font cache; this may take a moment" message. The cache is stored in MPLCONFIGDIR, which by default is ~/.cache/matplotlib on Linux and ~/.matplotlib on macOS. If that directory doesn't persist between runs, every run pays the full cost. This commonly happens with:
- Docker containers and CI runners started fresh each time
- sandboxed build/test tools that don't keep the home directory's cache
- new virtual environments or users with a different
MPLCONFIGDIR
Measurements
Apple M1 (8 GB), macOS, Python 3.12. "Empty cache" means MPLCONFIGDIR pointed at an empty directory.
|
Empty font cache |
Cache already built |
import matplotlib.pyplot |
17.0 s |
— |
import spatialmath, before #198 (f6a572c6^) |
17.6 s |
1.1 s |
import spatialmath, after #198 (current master) |
0.75 s |
0.7 s |
Before #198, import spatialmath imported matplotlib.pyplot, so every spatialmath user paid this on a cold cache, including code that never plots. Since #198 the import is lazy, so the cost appears only at the first plot, and code that never plots never pays it.
How long the scan takes depends on how many fonts are installed. A minimal Linux container will usually be faster than macOS, but several seconds is typical.
Fix
spatialmath can't avoid this without dropping Matplotlib. If you plot in a fresh environment, keep the cache between runs:
- Docker: build the cache when building the image, so it's baked in:
RUN python -c "import matplotlib.pyplot"
- CI: cache the
MPLCONFIGDIR directory between jobs (e.g. actions/cache on ~/.cache/matplotlib), or run the line above in a setup step.
- Sandboxes: set
MPLCONFIGDIR to a persistent, writable directory.
Proposed docs change
Add a short "Slow first plot" troubleshooting note to the docs, with the explanation and fixes above.
Related: #198 (lazy Matplotlib import), #234 (remaining import-time costs from SciPy/SymPy).
Symptom
In a fresh environment, the first plot (or, before #198, plain
import spatialmath) can take 10–20 s. Later runs on the same machine are fast, so the delay is hard to reproduce on a long-lived development machine, but it can recur on every run in containers or CI.Cause
This is Matplotlib behaviour, not spatialmath code. The first time Matplotlib's font manager runs with no font cache, it scans every font installed on the system to build one. That's the "Matplotlib is building the font cache; this may take a moment" message. The cache is stored in
MPLCONFIGDIR, which by default is~/.cache/matplotlibon Linux and~/.matplotlibon macOS. If that directory doesn't persist between runs, every run pays the full cost. This commonly happens with:MPLCONFIGDIRMeasurements
Apple M1 (8 GB), macOS, Python 3.12. "Empty cache" means
MPLCONFIGDIRpointed at an empty directory.import matplotlib.pyplotimport spatialmath, before #198 (f6a572c6^)import spatialmath, after #198 (currentmaster)Before #198,
import spatialmathimportedmatplotlib.pyplot, so every spatialmath user paid this on a cold cache, including code that never plots. Since #198 the import is lazy, so the cost appears only at the first plot, and code that never plots never pays it.How long the scan takes depends on how many fonts are installed. A minimal Linux container will usually be faster than macOS, but several seconds is typical.
Fix
spatialmath can't avoid this without dropping Matplotlib. If you plot in a fresh environment, keep the cache between runs:
MPLCONFIGDIRdirectory between jobs (e.g.actions/cacheon~/.cache/matplotlib), or run the line above in a setup step.MPLCONFIGDIRto a persistent, writable directory.Proposed docs change
Add a short "Slow first plot" troubleshooting note to the docs, with the explanation and fixes above.
Related: #198 (lazy Matplotlib import), #234 (remaining import-time costs from SciPy/SymPy).