microsoft / microsoft/apm

[perf] Consolidated performance evidence: September 2026

Open
#2,974 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status/needs-triage type/automation type/performance
Dominant language
Python
Stars
3.8k
Forks
362
Avg merge
1d 17h
Merged PRs (30d)
132

Description

Performance Scan - 2026-09-14

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

Findings
[B] Linear scan inside a loop -- src/apm_cli/commands/uninstall/engine.py:189-260
  • Current: O(n*m) -- _stage_shared_local_survivors loops over
    packages_to_remove (n) and calls _surviving_local_refs_at_install_path
    (line 196), which itself linearly scans all of surviving_dependencies (m)
    on every call. The same helper is also called again per-package inside
    _dry_run_uninstall (line 756), doubling the cost on --dry-run.
  • Proposed: O(n+m) -- pre-index surviving_dependencies once into a
    dict[install_path, list[DependencyReference]] before either loop, then
    do an O(1) dict lookup per package instead of an O(m) scan.
  • Fix: Build a install_path -> [local survivors] dict once outside both
    loops in engine.py and replace the repeated calls to
    _surviving_local_refs_at_install_path with a lookup against that dict.
[E] Heavy top-level imports on CLI command modules -- src/apm_cli/commands/install.py:1-53
  • Current: apm.commands.install is imported eagerly by
    src/apm_cli/cli.py:38 for every CLI invocation, and it in turn performs
    53 top-level imports (agent_plugins, copilot_plugins, install.argv,
    install.artifactory_resolver, install.dry_run_plan, install.errors,
    install.gitlab_resolver, install.helpers.ref_reuse,
    install.manifest_helpers, install.finalization, install.helpers.security_scan,
    etc.) that are only exercised when the user actually runs apm install.
    Every other subcommand (e.g. apm view, apm config) pays this import
    cost at process startup.
  • Proposed: defer the install-only heavy imports (artifactory_resolver,
    gitlab_resolver, dry_run_plan, manifest_helpers, security_scan) to inside
    the install() command function body, keeping only what's needed for
    Click registration (the install callable itself) at module import time.
  • Fix: Move the imports in src/apm_cli/commands/install.py lines 14-51
    that are only referenced inside the install/helper function bodies to
    local imports inside those functions, following the existing pattern
    already used for close_install_contexts deferral elsewhere in the file.
[C] Unconditional directory walk fallback -- src/apm_cli/install/services.py:863-880
  • Current: O(n) unconditional -- when pack_files is empty (older bundle
    without bundle_files metadata), the code falls back to
    bundle_dir.rglob("*") and computes a full sha256 hash of every file in
    the bundle on every deploy for that bundle, with no caching between
    target loops in the same install run.
  • Proposed: this fallback is correctly gated behind if not pack_files:
    already (fast-path skip when bundle metadata is present), so this is a
    low-priority, borderline finding -- it only fires for legacy bundles
    lacking bundle_files, not on every install. Noting for awareness only;
    no action required unless legacy-bundle installs become a hot path.
Scan coverage
  • src/apm_cli/ (484 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 · copilot · auto · 105.2 AIC · ⌖ 6.75 AIC · ⊞ 10.1K ·

  • expires on Sep 21, 2026, 1:42 AM UTC

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with src/apm_cli/commands/uninstall/engine.py:189-260 and 756, then inspect src/apm_cli/commands/install.py:1-53 and src/apm_cli/cli.py:38. Confirm the repeated survivor scans and eager install imports before making changes. Done means indexing survivors once, deferring install-only imports, and preserving the existing CLI behavior; the legacy bundle fallback is awareness-only.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli, performance
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.