What's Changed
Headlines
- Free-threaded Python wheels on PyPI:
cp313tandcp314twheels for macOS and Windows, andcp314tfor Linux. Release builds now check that every wheel's native modules import, and that on free-threaded builds they don't re-enable the GIL. - Apple Silicon M4+ fix: on chips with SME, profiling numpy/Accelerate code could silently corrupt numerical results (#1056). CPU sampling on those chips no longer uses signals.
- Safer AI-provider keys: API keys are never embedded in generated HTML. The new opt-in
scalene view --api-keys-from-envserves them from memory over localhost instead. The GUI is now served from a private directory rather than the whole temp dir. - Correctness: fixes found by new formal models (TLA+ and Lean) of Scalene's sampling and attribution, including several divide-by-zero and unbounded-sampling bugs.
New feature work
- Publish free-threaded (cp313t/cp314t) wheels by @emeryberger in #1104
- Signal-free CPU sampling on Apple Silicon with SME (M4+) (#1056) by @emeryberger in #1058
- Add opt-in
scalene view --api-keys-from-envby @emeryberger in #1097 - Bound
--stacksCPU cost on processes with many Python threads (#1056) by @emeryberger in #1057 - Declare free-threaded safety for the
_scalene_unwindmodule by @emeryberger in #1065
Bug fixes
- Build on Windows for free-threaded Python by @rbo-corematic in #1102
- Fix free-threaded builds: limited-API module name, pydantic-core pin, mypy 2.4 by @emeryberger in #1103
- Preserve
ReplacementSemLockidentity across spawned processes by @HassanRady in #1099 - Prevent API credentials from being embedded in generated HTML by @HassanRady in #1095
- Serve the GUI from a private directory, not the whole temp dir by @emeryberger in #1100
- Fix profiling scripts with a UTF-8 BOM by @mameikagou in #1092
- Fix
UnicodeEncodeErrorfor non-ASCII file paths by @emeryberger in #1087 - Fix #1063: non-ASCII
--profile-onlyno longer crashes with SIGSEGV by @emeryberger in #1064 - Retry EINTR on poll/select so profiling signals don't break native blocking calls (#1060) by @emeryberger in #1062
- Fix "dictionary changed size during iteration" race in stack output by @emeryberger in #1067
- Fix divide-by-zero and unbounded-sampling bugs found by formalization by @emeryberger in #1077 and #1078
- Sync
requirements.txtwithpyproject.tomlruntime dependencies by @emeryberger in #1085 - Lowercase
scalene viewoption help to match the rest of the CLI by @emeryberger in #1101
Formal verification
- Add formal models (TLA+ and Lean) of Scalene's concurrency and correctness, and prove the profiler-correctness desideratum (unbiased, consistent attribution), the Poisson sampler, memory-sampler correctness and the Python/native classifier, in #1068, #1070, #1072, #1075, #1076, #1080, #1082, #1083 and #1084
Testing and CI
- CI fails when native modules don't import or tests don't collect by @emeryberger in #1105
- Free-threaded CI jobs run their tests again (#1089, #1103), and a test-suite
sys.executableleak no longer skips the free-threaded memory tests (#1066) - Deflaking: #1069, #1071, #1074, #1096
Note for free-threaded Python 3.13 users
pydantic-core no longer ships cp313t wheels and its newest releases can't be built from source there. Until that changes, install with:
pip install scalene "pydantic-core<=2.46.5"
New Contributors
- @mameikagou made their first contribution in #1092
- @HassanRady made their first contribution in #1095
- @rbo-corematic made their first contribution in #1102
Full Changelog: v2.3.0...v2.4.0