Repository navigation
lightspeed: stop measure_impacted when the benchmarks import the project from outside the repository - #8
Merged
Conversation
…ect from outside the repository
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Purpose
A task image can have two copies of the project: the repository as an editable install, and a regular wheel pulled in as a dependency. asv starts each benchmark as a script, and that process can import the wheel instead of the repository. Then the timings measure the wrong code. In
numpy#21464every benchmark imported numpy 1.22.3 fromsite-packages, so no patch was ever timed. This PR adds a probe that finds where the benchmark processes import the project from.measure_impactedstops withProjectShadowedbefore timing when a package comes from outside the repository.How it works
flowchart LR A[measure_impacted] --> B[import names of the changed files] B --> C[probe benchmark, same spawner as the real benchmarks] C --> D{every package file inside the repository?} D -- yes --> E[run_benchmarks] D -- no --> F[raise ProjectShadowed with the paths]The probe is a one-function benchmark suite in a temporary folder.
get_spawner(env, ..., launch_method)runs it throughasv/benchmark.py, the same way as a real benchmark. It first imports the real benchmark suite package, because its__init__.pycan changesys.path. Then it imports each package and writes__file__to a JSON file.Changes
project_imports.py.import_packages(paths, repo_root)gives the top-level import names of changed files:numpy/core/x.cgivesnumpy,src/skimage/a.pygivesskimage. A name is the first folder with an__init__.py.probe_imports(...)gives{package: file}.outside_root(...)keeps the packages whose real path is not inside the repository root. A meson orsrc/layout passes when its files are inside the root.Effect: callers can see where the benchmark processes import the project from.
Before: nothing checked this.
ProjectShadowedandcheck_project_importsinsession.py.ProjectShadowed(ASVError)has.paths, for example{"numpy": ".../site-packages/numpy/__init__.py"}.Effect: one call checks the packages and raises with the paths.
Before: no error type.
measure_impactedcalls the check beforerun_benchmarks. The new argumentpackages=[...]gives the import names explicitly. When it isNone, the names come from the changed files.Effect: a shadowed run stops before any timing, with the paths in the message.
Before: the run timed the other copy and reported a speedup near 1.0.
Usage
Verification
uv venv -p 3.11anduv pip install -e ".[test]", thenpytest test/test_lightspeed_project_imports.py test/test_lightspeed_survey.py: 6 passed. The tests coverspawnandforkserver: the repository copy passes, and a copy earlier on the path is reported with its path.numpy__numpy__21464, these files copied over the installed lsv, run through the task'slsv_measure.py:project shadowed: numpy -> /opt/conda/envs/asv_3.9/lib/python3.9/site-packages/numpy/__init__.py. After the wheel was removed, the same check passed and 4 selected benchmarks were timed.pydata__bottleneck__304andscikit-image__scikit-image__5399: the check passes and the timing is the same as before. Details are in the datasmith PR.Notes
initialize_diffcheckdoes not call the check. The task template removes the second copy before init.test (ubuntu-latest, 3.9)has 6 failures. The lastmainrun has the same 6 (test_environment_bench.pyx5,test_publish.py::test_branch_name_is_also_filename). The 5 new tests pass in CI.LSV_REFto this branch commit3df656d.