fix: detect free-threaded Python from venv and uv before setting PYTHONMALLOC - #539
not-matthias wants to merge 2 commits into
Conversation
…ONMALLOC Free-threaded CPython (3.13t+) refuses to start with PYTHONMALLOC=malloc, so the valgrind executor skips that override when the interpreter is free-threaded. The detection only probed `python` on the PATH, which misses the interpreter the benchmark actually runs under when it lives in a virtual environment or is selected by uv. Probe every interpreter the command could resolve to and skip the override if any of them is free-threaded: - `python` / `python3` on the PATH - `$VIRTUAL_ENV/bin/python` - `.venv/bin/python` in the benchmark working directory - the interpreter `uv python find $UV_PYTHON` resolves to; when uv has not downloaded it yet, classify the request string (`3.13t`, `+freethreaded`) directly The probe reads `sys.abiflags` instead of `sysconfig`, since `sysconfig` fails to import when `_PYTHON_SYSCONFIGDATA_NAME` is set for a different interpreter, which turned the old check into a false negative for exactly the free-threaded venvs it needs to detect.
Merging this PR will not alter performance
|
|
NOTE: This PR tries to fix the known cases when a free-threaded python can be used and try to not use the environment variable. However, there are many more cases that can bypass our checks (e.g. using custom compiled python). In the future, we can explore removing |
|
|
|
||
| let mut candidates: Vec<PathBuf> = vec![PathBuf::from("python"), PathBuf::from("python3")]; | ||
| if let Some(venv) = std::env::var_os("VIRTUAL_ENV") { | ||
| candidates.push(Path::new(&venv).join("bin/python")); | ||
| } | ||
| candidates.push(cwd.join(".venv/bin/python")); |
There was a problem hiding this comment.
Benchmark commands can invoke a free-threaded interpreter through a name or path outside this fixed candidate list, such as
python3.13t script.py or a pytest console script from a custom-named virtual environment. Those commands are accepted as arbitrary shell commands, but detection checks only python, python3, two conventional virtual-environment paths, and UV_PYTHON. The detector therefore returns false, measure sets PYTHONMALLOC=malloc, and the free-threaded interpreter refuses to start. Resolve or probe the interpreter used by the configured command rather than assuming this list covers every possible interpreter.
Knowledge Base Used: Valgrind measurement
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/executor/valgrind/helpers/python.rs
Line: 20-25
Comment:
Benchmark commands can invoke a free-threaded interpreter through a name or path outside this fixed candidate list, such as `python3.13t script.py` or a `pytest` console script from a custom-named virtual environment. Those commands are accepted as arbitrary shell commands, but detection checks only `python`, `python3`, two conventional virtual-environment paths, and `UV_PYTHON`. The detector therefore returns false, `measure` sets `PYTHONMALLOC=malloc`, and the free-threaded interpreter refuses to start. Resolve or probe the interpreter used by the configured command rather than assuming this list covers every possible interpreter.
**Knowledge Base Used:** [Valgrind measurement](https://app.greptile.com/codspeed/-/custom-context/knowledge-base/codspeedhq/codspeed/-/docs/valgrind-measurement.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Add an experimental flag that unsets PYTHONMALLOC for simulation runs, allowing integrations to validate workloads without the forced malloc allocator before it becomes the default behavior.
Problem
Free-threaded CPython (3.13t+) refuses to start with
PYTHONMALLOC=malloc. The valgrind executor already skips that override when it detects a free-threaded interpreter, but the detection only probedpythonon thePATH. It missed the interpreter the benchmark actually runs under when that interpreter lives in a virtual environment or is selected byuv, so runs usingastral-sh/setup-uvwithpython-version: 3.13tstill failed.Change
Probe every interpreter the benchmark command could resolve to, and skip the override if any of them is free-threaded:
python/python3on thePATH$VIRTUAL_ENV/bin/python.venv/bin/pythonin the benchmark working directoryuv python find $UV_PYTHONresolves to (setup-uvexportsUV_PYTHONfrom itspython-versioninput).uvdownloads interpreters lazily, so when the request is not installed yet the request string itself (3.13t,+freethreaded) decides.The probe now reads
sys.abiflagsinstead ofsysconfig.get_config_var('Py_GIL_DISABLED').import sysconfigfails when_PYTHON_SYSCONFIGDATA_NAMEis set for a different interpreter (common in Nix shells), which turned the old check into a silent false negative for exactly the venvs it needs to detect.Verification
Release-mode smoke runs against real interpreters created with
uv venv:.venvin cwd.venvin cwdUV_PYTHON=3.14t(installed), no venvUV_PYTHON=3.13t(not installed), no venvUV_PYTHON=3.12, no venvVIRTUAL_ENV=<3.14t venv>, cwd has no venvPlus
rstestcases for theUV_PYTHONrequest-string classifier.