Skip to content

feat(watcher): port watchpack safeTime/mtime-accuracy to native watcher#14267

Draft
stormslowly wants to merge 2 commits into
web-infra-dev:mainfrom
stormslowly:feat/native-watcher-safetime
Draft

feat(watcher): port watchpack safeTime/mtime-accuracy to native watcher#14267
stormslowly wants to merge 2 commits into
web-infra-dev:mainfrom
stormslowly:feat/native-watcher-safetime

Conversation

@stormslowly

Copy link
Copy Markdown
Contributor

Why

The native watcher returned empty fileTimeInfoEntries / contextTimeInfoEntries (left as a // TODO), so compiler.fileTimestamps / contextTimestamps were empty. Persistent-cache snapshot validation then degrades to "trust the changedFiles set only", which can miss or over-invalidate across processes — the JS (watchpack) path does populate these via collectTimeInfoEntries, so this closes a parity gap.

What

Port watchpack's safeTime / mtime-accuracy mechanism into rspack_watcher:

  • FS_ACCURACY global (2000ms, monotonically ratchets down) + ensureFsAccuracy resolution detection
  • per-entry { safe_time, timestamp, accuracy } with the initial-scan regime (min(now, mtime) + FS_ACCURACY) and the real-time regime (now, accuracy 0), including the attribute-only within-window skip
  • fixupEntryAccuracy lazy tightening on read + directory safe_time aggregated from descendant files
  • expose via napi getTimeInfo(); NativeWatchFileSystem now fills both maps and getInfo()

accuracy is kept internal — rspack's FileSystemInfoEntry exposes only { safeTime, timestamp }, matching webpack's public contract.

Before / After

// Before
callback(err, new Map(), new Map(), changed, removed); // TODO

// After
const timeInfo = nativeWatcher.getTimeInfo();
callback(err, toTimeInfoMap(timeInfo.fileTimeInfoEntries),
         toTimeInfoMap(timeInfo.contextTimeInfoEntries), changed, removed);

Test

  • cargo test -p rspack_watcher — ported watchpack safeTime characterization tests (FS_ACCURACY ladder, fixup, initial/event regimes, within-window skip, dir aggregation)
  • watchpack DirectoryWatcherExtra suite green (reference parity)
  • NativeWatcher.part1/2/3 JS suites green (230 cases)

Draft: opened to produce a canary for rstest native-watcher stress testing.

The native watcher returned empty fileTimeInfoEntries / contextTimeInfoEntries
(left as a TODO), so compiler.fileTimestamps / contextTimestamps were empty and
the persistent-cache snapshot degraded to "trust changedFiles only".

Port watchpack's safeTime mechanism into rspack_watcher:
- FS_ACCURACY global + ensureFsAccuracy resolution detection
- per-entry { safe_time, timestamp, accuracy } with initial/event regimes
- fixupEntryAccuracy lazy tightening + directory safe_time aggregation
- expose via napi getTimeInfo(); populate the two maps and getInfo() in
  NativeWatchFileSystem

accuracy is kept internal: rspack's FileSystemInfoEntry exposes only
{ safeTime, timestamp }, matching webpack's public contract.
@codspeed-hq

codspeed-hq Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will degrade performance by 2.4%

⚠️ Unknown Walltime execution environment detected

Using the Walltime instrument on standard Hosted Runners will lead to inconsistent data.

For the most accurate results, we recommend using CodSpeed Macro Runners: bare-metal machines fine-tuned for performance measurement consistency.

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 1 regressed benchmark
✅ 51 untouched benchmarks
⏩ 40 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation js@collect imported identifiers 225 µs 230.5 µs -2.4%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing stormslowly:feat/native-watcher-safetime (4f1743a) with main (ac43bc2)

Open in CodSpeed

Footnotes

  1. 40 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@codspeed-hq

codspeed-hq Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Unable to generate the flame graphs

The performance report has correctly been generated, but there was an internal error while generating the flame graphs for this run. We're working on fixing the issue. Feel free to contact us on Discord or at support@codspeed.io if the issue persists.

The directory-aggregation test used a Unix-style "/project/src" path, which
is not absolute on Windows — update() relativized it (joined cwd) so the
file's parent chain no longer matched the registered directory. Build the
paths from std::env::temp_dir() instead. Also bump the real-change test sleep
to 50ms to clear Windows' ~15.6ms SystemTime granularity.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant