Skip to content

Windows: lstat bottleneck causes 2-3x slower performance vs Mac (59% of CPU time) #85262

Description

@211-lee

Problem

OpenClaw on Windows is 2-3x slower than on Mac. CPU profiling (120s full flow) reveals lstat system calls as the dominant bottleneck:

  • 81s non-idle time, of which 47.8s (59%) is spent in lstat
  • safeRealpathSync / isPathInsideWithRealpath called ~48,000 times → ~976,000 lstat calls
  • Most callers do not pass a cache parameter, causing the same path prefixes to be repeatedly resolved with identical results
  • Windows single lstat: 49µs vs Mac 1.1µs (45x slower per call) — multiplied by ~1M calls = 47s

Root Cause

Three re-export modules (path-safety.ts, path-guards.ts, boundary-path.ts) forward safeRealpathSync and isPathInsideWithRealpath from @openclaw/fs-safe/path without any cross-call caching. Each invocation starts fresh, even for identical path prefixes that were just resolved moments ago.

Proposed Fix

Inject a global Map<string, string> cache at the re-export layer:

  1. path-safety.ts: Wrap safeRealpathSync with a dual-layer cache (global + caller-local)
  2. path-guards.ts: Import from path-safety.js (instead of directly from @openclaw/fs-safe/path) so all 25 importing files benefit from the global cache
  3. boundary-path.ts: Add input→output result cache for resolvePathViaExistingAncestorSync

Rewrite isPathInsideWithRealpath to call the cached safeRealpathSync from its own module.

Benchmark Results (120s CPU Profile, before → after)

Metric Before After Improvement
lstat total 47,834ms 8,135ms -83%
safeRealpathSync direct lstat ~14,000ms 743ms -95%
resolvePathViaExistingAncestorSync 4,300ms 61ms -99%
chat.send → lane enqueue 17-20s 5.4s -70%

Implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-live-reproClawSweeper needs live local, crabbox, or manual validation to confirm this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🐚 platinum hermitGood issue quality with a plausible reproduction path needing some confirmation.staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions