Repository navigation
perf(compile): remove redundant work from instruction placement - #3379
Open
Sergei Kozyrev (sekosen) wants to merge 4 commits into
Open
Sergei Kozyrev (sekosen) wants to merge 4 commits into
Sergei Kozyrev (sekosen) wants to merge 4 commits into
Conversation
Sergei Kozyrev (sekosen)
requested review from
Daniel Meppiel (danielmeppiel) and
Sergio Sisternes (sergio-sisternes-epam)
as code owners
October 24, 2026 12:15
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
Static review identified no blocking issues in the focused optimizations and regression coverage; tests were not executed during this review.
No open issues 🎉
What changed in this PR
This PR addresses #2969 by reducing repeated work in ContextOptimizer, improving instruction-placement performance on large projects while preserving existing matching and symlink behavior.
Changes:
- Cache file-relative paths and resolved directories, clearing both caches when project structure is analyzed.
- Compute the depth mean once and stop candidate coverage checks at the first uncovered directory.
- Add regression tests for performance, cache resets, scoring, symlinks, and compile-output parity.
| File | Description |
|---|---|
tests/unit/compilation/test_context_optimizer_symlinked_files.py |
Pins matching behavior for internal, external, dangling, and looping symlinks. |
tests/unit/compilation/test_context_optimizer_phase3.py |
Adds an exact distribution-score assertion. |
tests/unit/compilation/test_context_optimizer_perf_regressions.py |
Checks cache resets, resolution counts, mean computation, and short-circuiting. |
tests/integration/test_compile_placement_parity_e2e.py |
Checks placement and file inclusion through the in-process CLI. |
src/apm_cli/compilation/context_optimizer.py |
Adds path caches and removes redundant scoring and coverage work. |
Review effort: Balanced
Cover how symlinked files match applyTo patterns (in-project, outside the project, dangling, colliding with a real file, and symlink loops on Python < 3.13) and pin the exact distribution score. All of these pass on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run the real CLI on a project with ordinary files, in-project, outside and dangling symlinks, excluded paths and a .github hidden root, and pin the matched directories and generated AGENTS.md files. Passes on main. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Large projects with overlapping scoped applyTo patterns spent most of compile time repeating the same work in ContextOptimizer: - cache each file's project-relative path instead of resolving it per pattern check - resolve each directory once instead of on every coverage check - compute the depth mean once instead of once per directory - stop checking a placement candidate at its first uncovered directory Both new caches are cleared whenever the project structure is analyzed. Matching and placement results are unchanged; existing tests and the tests from the previous two commits pass without changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fail if the per-call caches leak between optimize_instruction_placement calls, the depth mean is recomputed per directory, a candidate check keeps going after its first miss, or a file or directory is resolved more than once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
|
@microsoft-github-policy-service agree |
Sergei Kozyrev (sekosen)
force-pushed
the
perf/placement-large-tree-scaling-v3
branch
from
October 24, 2026 12:33
a7a0098 to
2dd6155
Compare
This branch has not been deployed
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.
Description
On large projects with overlapping scoped
applyTopatterns,apm compilespends most of its time inContextOptimizerrepeating the same work. This PR removes that repeated work. Results are unchanged._calculate_distribution_scoreis computed once instead of once per directory.Both caches are in memory and are cleared each time the project structure is analyzed. Matching,
CompileInventoryuse, symlinks, exclusions and hidden roots are unchanged.Benchmark
Run with sekosen/apm-placement-benchmark:
apm compile --dry-run --no-links --target claude, fastest of 3 runs, peak RSS. Before ismainat29200432.proj_smallproj_1000proj_2000proj_10000Issue and approved scope
Issue: #2969
Human scope-approval comment: #2969 (comment)
Replaces #2878 with a new history and without the excluded symlink behavior change.
Fixes #2969
Commits
test(compile): pin placement behavior before the perf fix: unit parity tests, pass onmain.test(compile): cover placement and file inclusion through apm compile: end-to-end test through the real CLI, passes onmain.perf(compile): remove redundant work from placement: the fix. Existing tests pass unmodified.test(compile): catch regressions of the placement perf fix: regression tests for each optimization. Each was checked to fail when the code it guards is broken."Done when" coverage
test_depth_mean_computed_oncetest_file_resolved_once_across_patterns,test_directory_resolved_once_per_calltest_candidate_check_stops_at_first_uncovered_directorytest_rel_path_cache_entry_does_not_survive,test_resolved_dir_cache_entry_does_not_survivetest_context_optimizer_symlinked_files.py,test_compile_placement_parity_e2e.pytest_compile_placement_parity_e2e.py(compilation.exclude,node_modules,.github, untargeted hidden dir)apm compilecoveragetest_compile_placement_parity_e2e.pyCompileInventoryNotes for reviewers
resolve()for directories. On Windows, a junction can put an unresolved path into the inventory, so skipping it could change placement. This PR keepsresolve()and caches the result instead.mainand this branch were compared on a fixture with in-project, external, dangling, looping and directory symlinks, nested.git, excluded and hidden directories, odd file names, an aliased base dir and emulated Windows junctions, across 41 patterns. No differences.main, generatedAGENTS.mdfiles count as project files on the next compile, so a rerun can place instructions differently. Out of scope; the e2e test deletes them between runs.Type of change
Testing
Each commit passes
tests/unit/compilationand the compile e2e tests on Python 3.10, 3.12 and 3.14. Lint job checks and ratchet tests pass locally.Spec conformance (OpenAPM v0.1)