floordiv, rfloordiv, absfirst, abssecond, and rpow are UDFs, so every
process that touched one paid its numba compile again. They are plain
module-level functions, which is exactly the case numba can cache, so
that cost belongs once per machine rather than once per process.
Thread the flag through as a private keyword-only `_cache` on
register_new into _build, where it reaches numba.njit alongside the
existing error_model. Keeping it private avoids widening the public API
for something no caller outside this module should set. Ops registered by
users stay uncached: numba keys a cache entry on a stable on-disk source,
which lambdas and interactively defined functions do not have.
Measured here, fresh process, medians of 3, load average ~4 on a shared
machine so read these as indicative. First-touch floordiv alone: 434 ms
uncached, 347 ms warm (-20%). First-touch of all five: 1337 ms uncached,
733 ms warm (-45%). Writing a cold cache costs about 107 ms once for all
five (1444 ms on the run that populates it).
What stays: the remaining ~733 ms is numba/LLVM startup and per-process
object linking, which no on-disk cache removes. In-process dispatch once
an op is built is untouched. The first process on a machine is slightly
slower, not faster.
Read-only installs are safe, verified rather than assumed. With
graphblas/core/operator and its __pycache__ chmod'd a-w, the run wrote
zero files in-tree and 66 .nbi/.nbc files under ~/Library/Caches/numba,
with empty stderr under `python -W always`. The NumbaWarning in
numba/core/caching.py is a source-content check, not a filesystem one.
docs/user_guide/udf.rst gains a "Compilation caching" section covering the
cache location, the read-only fallback, and why user ops are excluded.
floordiv, rfloordiv, absfirst, abssecond, and rpow are UDFs, so every
process that touched one paid its numba compile again. They are plain
module-level functions, which is exactly the case numba can cache, so
that cost belongs once per machine rather than once per process.
Thread the flag through as a private keyword-only _cache on
register_new into _build, where it reaches numba.njit alongside the
existing error_model. Keeping it private avoids widening the public API
for something no caller outside this module should set. Ops registered by
users stay uncached: numba keys a cache entry on a stable on-disk source,
which lambdas and interactively defined functions do not have.
Measured here, fresh process, medians of 3, load average ~4 on a shared
machine so read these as indicative. First-touch floordiv alone: 434 ms
uncached, 347 ms warm (-20%). First-touch of all five: 1337 ms uncached,
733 ms warm (-45%). Writing a cold cache costs about 107 ms once for all
five (1444 ms on the run that populates it).
What stays: the remaining ~733 ms is numba/LLVM startup and per-process
object linking, which no on-disk cache removes. In-process dispatch once
an op is built is untouched. The first process on a machine is slightly
slower, not faster.
Read-only installs are safe, verified rather than assumed. With
graphblas/core/operator and its pycache chmod'd a-w, the run wrote
zero files in-tree and 66 .nbi/.nbc files under ~/Library/Caches/numba,
with empty stderr under python -W always. The NumbaWarning in
numba/core/caching.py is a source-content check, not a filesystem one.
docs/user_guide/udf.rst gains a "Compilation caching" section covering the
cache location, the read-only fallback, and why user ops are excluded.
Stack created with GitHub Stacks CLI • Give Feedback 💬