Skip to content

Windows perf: WinPython locator scans C:\, D:\, E:\ drive roots on every refresh #453

@eleanorjboyd

Description

@eleanorjboyd

Summary

The WinPython locator scans the root of C:\, D:\, and E:\ (plus ~/Downloads, ~/Desktop, ~/Documents, Program Files, Program Files (x86), etc.) on every refresh RPC. There is no cache, no opt-in, and no equivalent locator on macOS/Linux. This is the most plausible single cause of the Windows-vs-macOS p90 gap (Windows p90 ~11.3s on the slow cohort vs ~0.8s on macOS).

Full investigation: docs/windows-perf-investigation.md (Issue 1).

Where

What it does today

for drive in ['C', 'D', 'E'] {
    let drive_path = PathBuf::from(format!("{}:\\", drive));
    paths.push(drive_path.clone());          // root of the drive
    paths.push(drive_path.join("WinPython"));
    paths.push(drive_path.join("Python"));
}

For each existing search path, find() calls fs::read_dir(...) then path.is_dir() on every entry, then a second fs::read_dir inside matching directories.

Why this hurts on Windows

  • Drive roots commonly contain hundreds of unrelated folders. Every is_dir() is a stat syscall that triggers Defender real-time scanning.
  • ~/Downloads is a notorious slow path: large and full of zip/installer artifacts that Defender re-scans aggressively.
  • find() has no cache (unlike WindowsStore and WindowsRegistry), so this work runs on every refresh RPC.
  • WinPython is a niche portable distribution — the cost-benefit of scanning every drive root on every machine is poor.
  • There is no equivalent locator on macOS/Linux. This asymmetry alone could account for a significant chunk of the 5× p90 gap.

Proposed fix

  1. Drop drive-root and Program Files entries from get_winpython_search_paths(). Keep only ~/WinPython and an opt-in env var (e.g. WINPYTHON_HOME).
  2. Add a per-process cache to WinPython::find() mirroring WindowsStore / WindowsRegistry.
  3. Follow-up: make WinPython lazy — only run find() when the user opts in or when a workspace path resolves into a WinPython tree.

Estimated change size: ~10 lines for (1), ~30 lines for (2).

Validation

The extension can confirm the impact today by attaching RefreshPerformance.locators["WinPython"] (already emitted via the RefreshPerformance telemetry notification) to its pet.refresh event and slicing the slow Windows cohort. A long tail concentrated on WinPython would confirm the diagnosis.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions