Skip to content

Rebuilt CLI watcher around new fswatch package#4026

Open
johnfav03 wants to merge 16 commits into
microsoft:mainfrom
johnfav03:cli-watcher-parcel-integration
Open

Rebuilt CLI watcher around new fswatch package#4026
johnfav03 wants to merge 16 commits into
microsoft:mainfrom
johnfav03:cli-watcher-parcel-integration

Conversation

@johnfav03
Copy link
Copy Markdown
Contributor

The CLI watcher (tsgo --watch) was previously implemented with a polling-based approach, using a Run() loop - the key disadvantage of this system is that I would still call Stat() on tracked files even when they didn't change, which yielded an idle CPU usage of ~5% in the vscode repo.

With the addition of the fswatch package (PR #3980), we can rebuild the watcher around OS-level filesystem events, which results in an idle CPU usage of <1% on average in the vscode repo.

⚠️ Note: this branch is based on the fswatch branch, so only commits from 8230a72 onward contain relevant changes.

Copilot AI review requested due to automatic review settings May 21, 2026 21:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request rebuilds tsgo --watch around the new internal/fswatch package (OS filesystem events + debouncing) instead of the previous polling loop, while keeping internal/vfs/vfswatch as a baseline-snapshot change detector for tracked compiler inputs.

Changes:

  • Replaces the CLI watch loop with an event-driven fswatch subscription (recursive + ignore filter) and coalesced DoCycle signaling.
  • Simplifies internal/vfs/vfswatch by removing polling/timing/debounce machinery, leaving only snapshot + compare logic.
  • Introduces a new multi-backend internal/fswatch implementation (fanotify/inotify/kqueue/FSEvents/ReadDirectoryChangesW), plus extensive tests and documentation.

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
internal/vfs/vfswatch/vfswatch.go Removes polling-based watcher loop; keeps snapshot+compare watch-state logic.
internal/vfs/vfswatch/vfswatch_test.go Updates tests for the new NewFileWatcher(fs) constructor.
internal/vfs/vfswatch/vfswatch_race_test.go Updates race/fuzz tests to remove polling-interval related coverage.
internal/fswatch/windows.go Adds Windows backend based on ReadDirectoryChangesW with overlapped I/O.
internal/fswatch/watcher.go Adds core fswatch API surface, watcher lifecycle, per-dir state, and callback filtering.
internal/fswatch/walkdir.go Adds generic walkDir implementation (portable baseline).
internal/fswatch/walkdir_windows.go Adds Windows-optimized walkDir using FindFirstFile/FindNextFile.
internal/fswatch/walkdir_unix.go Adds Unix walkDir using getdents/getdirentries for fewer stats.
internal/fswatch/walkdir_test.go Adds tests validating walkDir behavior (symlinks, perms, entries, callbacks).
internal/fswatch/walkdir_other.go Routes unsupported OSes to the generic walkDir implementation.
internal/fswatch/walkdir_dirent_noreclen.go Adds DragonFlyBSD dirent helpers for reclen/inode extraction.
internal/fswatch/walkdir_dirent_linux.go Adds Linux dirent helpers for reclen/inode extraction.
internal/fswatch/walkdir_dirent_fileno.go Adds FreeBSD/OpenBSD/NetBSD dirent helpers for reclen/inode extraction.
internal/fswatch/walkdir_dirent_darwin.go Adds macOS dirent helpers for reclen/inode extraction.
internal/fswatch/testutil_test.go Adds retry-capable test harness to reduce platform flake impact.
internal/fswatch/README.md Documents fswatch usage, watcher selection, and error semantics.
internal/fswatch/LICENSE Adds upstream MIT license attribution.
internal/fswatch/kqueue.go Adds kqueue backend for BSD/macOS (fd-per-entry model).
internal/fswatch/inotify_linux.go Adds inotify backend for Linux.
internal/fswatch/fanotify_linux.go Adds fanotify backend for Linux with rename probing/fallback.
internal/fswatch/fanotify_linux_test.go Adds Linux fanotify-specific tests (availability, parsing, shutdown, cross-watcher).
internal/fswatch/fsevents_darwin.go Adds macOS FSEvents backend (event classification and lifecycle).
internal/fswatch/fsevents_darwin_ffi.go Adds cgo-free CoreFoundation/CoreServices/libdispatch FFI plumbing and NFC normalization helpers.
internal/fswatch/fsevents_darwin_ffi.s Adds shared assembly trampolines and exported trampoline addresses.
internal/fswatch/fsevents_darwin_ffi_arm64.s Adds arm64 FSEvents Create trampoline + callback shim assembly.
internal/fswatch/fsevents_darwin_ffi_amd64.s Adds amd64 FSEvents Create trampoline + callback shim assembly.
internal/fswatch/fsevents_darwin_ffi_arm64_test.go Adds static disassembly-based test ensuring the arm64 callback only touches safe registers.
internal/fswatch/fsevents_darwin_nfd_test.go Adds macOS Unicode normalization regression tests (NFD/NFC mismatch scenarios).
internal/fswatch/event.go Adds event kinds and per-path coalescing state machine.
internal/fswatch/eventlist_test.go Adds unit tests for event coalescing and atomic drain semantics.
internal/fswatch/debounce.go Adds per-backend debounce mechanism (min/max coalescing windows).
internal/fswatch/CHANGES.md Documents divergence from upstream @parcel/watcher and lists bugfixes/features.
internal/fswatch/cgmanifest.json Adds component governance manifest pointing at upstream source commit/tag.
internal/fswatch/canonicalize_other.go Adds no-op path canonicalization for non-darwin platforms.
internal/fswatch/canonicalize_darwin.go Adds NFC canonicalization for macOS path consistency.
internal/execute/watcher.go Rebuilds CLI watcher to subscribe to fswatch events and signal DoCycle asynchronously.
.golangci.yml Updates linter exclusion pattern to include internal/fswatch.

Comment thread internal/vfs/vfswatch/vfswatch.go
Comment thread internal/execute/watcher.go
Comment thread internal/execute/watcher.go Outdated
Comment thread internal/execute/watcher.go Outdated
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.

3 participants