Skip to content

[perf-scan] 2026-08-13 -- performance opportunities found #2567

Description

@github-actions

Performance Scan - 2026-08-13

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

Findings

[A] Quadratic nested loop -- uninstall/engine.py:74-94 and 178-250

  • Current: O(n*m) -- _surviving_local_refs_at_install_path iterates all surviving_dependencies (m) for every package in packages_to_remove (n); called twice: lines 178-250 and 734-753.
  • Proposed: O(n+m) with a pre-built index.
  • Fix: Before the outer loop, build install_path_to_survivors: dict[Path, list] = {} by iterating surviving_dependencies once (grouping by get_install_path), then replace the inner linear scan with a single dict lookup per package.

[D] Triple dep_names recomputation -- policy/policy_checks.py:155,198,251

  • Current: O(3n) -- _check_required_packages (line 155), _check_required_packages_deployed (line 198), and _check_required_executable_untrusted (line 251) each independently rebuild dep_names = {dep.get_canonical_dependency_string().split("#")[0] for dep in deps} from the same deps list. All three are called in sequence from the main runner at lines 1239-1245.
  • Proposed: O(n) -- compute once and reuse.
  • Fix: Compute dep_names once in the main runner (or a shared helper) and pass it as a parameter to each check function that needs it.

[B] Linear scan in _map_grants per (package, exec_type) pair -- security/executables.py:256-262 (low priority)

  • Current: O(m) per call -- _map_grants iterates all entries in grant_map.items() performing _strip_version comparisons for each; called up to 4 times per (package, exec_type) pair from _resolve_trust (lines 327-343), and materialize_exec_map calls _resolve_trust for every candidate key crossed with every exec type.
  • Proposed: O(1) per lookup after O(m) pre-build -- index grant maps as {_strip_version(k): (k, entry)} once before the resolution loop.
  • Fix: Pre-build a version-blind index for each grant map before calling materialize_exec_map or the tight exec_status_for_declaration loop (lines 742-760), then replace the linear scan with a dict lookup.

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.2 AIC · ⌖ 6.24 AIC · ⊞ 7.3K ·

  • expires on Aug 20, 2026, 1:45 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

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions