Skip to content

[perf-scan] 2026-08-12 -- performance opportunities found #2562

Description

@github-actions

Performance Scan - 2026-08-12

Automated scan of src/apm_cli/ for algorithmic performance anti-patterns.
2 finding(s) identified.

Findings

[E] Heavy Top-Level Import -- src/apm_cli/commands/update.py:62-68

  • Current: O(startup) -- from git.exc import GitCommandError and from ..deps.github_downloader import GitHubPackageDownloader are loaded at module level; since cli.py eagerly imports all command modules, gitpython and the full download machinery load on every apm invocation regardless of which sub-command is run (e.g. apm list, apm doctor).
  • Proposed: O(0) at startup -- import cost deferred to invocation time by moving these imports inside the update callback function body.
  • Fix: Move from git.exc import GitCommandError, from ..deps.github_downloader import GitHubPackageDownloader, and the revision_pins imports inside the update() function body so they are only imported when apm update is actually invoked.

[B] Double Linear Scan on List -- src/apm_cli/models/dependency/reference.py:1155-1156, 1322-1323, 1397-1398, 1503-1504

  • Current: O(2n) per occurrence -- the pattern if "_git" in parts: git_idx = parts.index("_git") performs two sequential O(n) list scans (one membership check, one index lookup) where a single scan suffices. Appears four times across parse methods; called once per dependency string parsed at install/update time.
  • Proposed: O(n) with a single scan -- use try: git_idx = parts.index("_git") ... except ValueError: pass or precompute the index once.
  • Fix: Replace each if "_git" in parts: idx = parts.index("_git") pair with try: idx = parts.index("_git"); parts = parts[:idx] + parts[idx+1:] except ValueError: pass to eliminate the redundant membership scan.

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)

Notes:

  • Pattern A: No confirmed O(n^2) loops found; context_optimizer.py uses pattern/result caching; security/executables.py uses frozenset for O(1) membership tests.
  • Pattern C: http_cache.py already implements fast-path skip before full directory scan in _enforce_size_cap().
  • Pattern D: os.getenv calls in registry/operations.py loop over different variable names per iteration (not the same key fetched twice).
  • Pattern F: install/phases/download.py already uses ThreadPoolExecutor for parallel downloads; sequential subprocess loops in validation.py are fallback probes (later iterations depend on prior failures).

Generated by Daily Performance Scanner · 190.9 AIC · ⌖ 6.3 AIC · ⊞ 7.3K ·

  • expires on Aug 19, 2026, 1:48 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/automationAutomation script, workflow, gh-aw, dependabot config.type/performanceLatency, throughput, memory, install time.

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions