Performance Scan - 2026-08-21
Automated scan of src/apm_cli/ for algorithmic performance anti-patterns.
2 finding(s) identified.
Findings
[C] Unconditional Expensive Operation -- src/apm_cli/compilation/context_optimizer.py:874-875
- Current: O(F x P) filesystem syscalls --
file_path.resolve() and
self.base_dir.resolve() are called inside _file_matches_pattern for
every (file, **-pattern) pair. self.base_dir is already a resolved path
(set at construction, line 144), so self.base_dir.resolve() is a redundant
syscall on every call. file_path.resolve() repeats for every file that
reaches the ** branch, even though file paths are constructed once during
_analyze_project_structure.
- Proposed: O(1) base-dir resolve (use
self.base_dir directly) + O(F) total
file-path resolves (pre-compute once during _analyze_project_structure).
- Fix: Store resolved file paths in
_files_by_directory during
_analyze_project_structure and replace self.base_dir.resolve() with
self.base_dir at line 875; _file_matches_pattern then needs no syscalls
on the ** branch.
[C] Unconditional Expensive Operation -- src/apm_cli/compilation/context_optimizer.py:1406
- Current: O(D x depth x I)
Path.resolve() syscalls -- _is_instruction_relevant
calls working_directory.resolve() (line 1406) for every non-global instruction.
Its sole caller, analyze_context_inheritance, passes the same working_directory
for all inner-loop iterations (lines 341-349), so the resolve is repeated
O(depth x I) times per directory, and _calculate_optimization_stats calls
analyze_context_inheritance for every directory D in the project, giving
O(D x depth x I) redundant resolves during the stats phase.
- Proposed: O(D)
resolve() calls total for the stats pass.
- Fix: Compute
resolved_working_dir = working_directory.resolve() once at the
top of analyze_context_inheritance and pass the pre-resolved path into
_is_instruction_relevant (add a resolved_working_dir parameter or hoist
the resolve into the caller).
Scan coverage
- src/apm_cli/ (430 files scanned)
- Patterns checked: A (quadratic loops), B (linear scan in loop),
C (unconditional expensive ops), D (redundant config parsing),
E (heavy top-level imports), F (sequential independent I/O)
Generated by Daily Performance Scanner · 133 AIC · ⌖ 6.3 AIC · ⊞ 7.3K · ◷
Performance Scan - 2026-08-21
Automated scan of src/apm_cli/ for algorithmic performance anti-patterns.
2 finding(s) identified.
Findings
[C] Unconditional Expensive Operation -- src/apm_cli/compilation/context_optimizer.py:874-875
file_path.resolve()andself.base_dir.resolve()are called inside_file_matches_patternforevery (file,
**-pattern) pair.self.base_diris already a resolved path(set at construction, line 144), so
self.base_dir.resolve()is a redundantsyscall on every call.
file_path.resolve()repeats for every file thatreaches the
**branch, even though file paths are constructed once during_analyze_project_structure.self.base_dirdirectly) + O(F) totalfile-path resolves (pre-compute once during
_analyze_project_structure)._files_by_directoryduring_analyze_project_structureand replaceself.base_dir.resolve()withself.base_dirat line 875;_file_matches_patternthen needs no syscallson the
**branch.[C] Unconditional Expensive Operation -- src/apm_cli/compilation/context_optimizer.py:1406
Path.resolve()syscalls --_is_instruction_relevantcalls
working_directory.resolve()(line 1406) for every non-global instruction.Its sole caller,
analyze_context_inheritance, passes the sameworking_directoryfor all inner-loop iterations (lines 341-349), so the resolve is repeated
O(depth x I) times per directory, and
_calculate_optimization_statscallsanalyze_context_inheritancefor every directory D in the project, givingO(D x depth x I) redundant resolves during the stats phase.
resolve()calls total for the stats pass.resolved_working_dir = working_directory.resolve()once at thetop of
analyze_context_inheritanceand pass the pre-resolved path into_is_instruction_relevant(add aresolved_working_dirparameter or hoistthe resolve into the caller).
Scan coverage
C (unconditional expensive ops), D (redundant config parsing),
E (heavy top-level imports), F (sequential independent I/O)