Skip to content

Leave the sealed system volume to the OS build instead of watching it - #3

Merged
jeffwall-curlewlabs merged 1 commit into
mainfrom
system-volume-watches
Oct 13, 2026
Merged

jeffwall-curlewlabs merged 1 commit into
mainfrom
system-volume-watches

Conversation

@jeffwall-curlewlabs

Copy link
Copy Markdown
Contributor

Bazel reads every watched file in full when a new server first checks a
repository's recorded inputs (RepoRecordedInput.File digests the file's
content). On macOS the search path is mostly /bin and /usr/bin, so that
check read every system tool. On one CI host the watches covered 1,214 files
and 277 MiB, and the first build after a boot spent 33.5 s on the check
without running the rule.

Those files sit on the sealed system volume, which changes only with the OS
build the key already records (sw_vers) and watches (SystemVersion.plist).

Change

  • An entry whose resolution stays on the system volume throughout (every
    directory it passes, every link it follows, and the file it reaches)
    contributes its name, mode and link target, not its content, and is not
    watched. A search path directory on the volume is not listed-watched.
  • An entry that passes through a link or a directory anywhere else stays
    digested and watched, even when it ends on the volume, because that part can
    change without an OS update. safaridriver, which links into the App
    cryptex, is one such entry and stays watched.
  • The volume is identified by statvfs().f_fsid of SystemVersion.plist.
    st_dev cannot tell the volumes apart on APFS: it reports the same device
    for /usr/bin and /usr/local.
  • README: the search path bullet, a "Not covered" entry for an unsealed system
    volume, and what "When the key changes" watches and why.

Linux takes the same path as before, so Linux keys are unchanged. Every macOS
host's key changes once. SCHEMA stays as it is, because the changed
identities cannot collide with old ones. The module version is not bumped
here, so one release can carry this and #2. The two merge cleanly.

Verification

  • Unit tests on Python 3.14 and Xcode's 3.9.6. The new macOS-only tests use
    the real system volume: /bin yields no watches, a same-directory link in
    /usr/bin is not watched, a scratch link to /bin/sh stays watched, and a
    path through a scratch directory link to /bin is not covered. Each of three
    mutations fails at least one of them: never matching the volume, dropping the
    per-directory check, and the simpler walk that checks only each link's
    resolved parent.
  • tests/check_platform.py passes on macOS 26.7 (arm64). Changed tools and
    bottles still re-execute in a running server, and fresh output bases still
    hit the disk cache.
  • Ruff 0.16.7 (check and format) and mypy 2.3.1 --strict pass.
  • Watches computed on a macOS 26.6.2 CI host, old vs new: 1,214 regular files
    (277.2 MiB) and 131 listings, down to 255 files (2.4 MiB) and 129 listings.
    Key computation on a warm cache went from 3.2-4.8 s to 0.7-0.8 s.
  • Bazel 9.2.0 on macOS 26.7, the default consumer, five new servers each on a
    warm page cache: @host_cache_key took 0.24-0.76 s before and 0.02-0.03 s
    after, with the rule never running. Its marker went from 1,229 FILE entries
    to 270.

Not measured: the cold case, the first build after a boot. Here it is bounded
by reading 2.4 MiB instead of 277 MiB.

Bazel reads every watched file in full when a new server first checks a
repository's recorded inputs. On macOS the search path is mostly /bin and
/usr/bin, so that check read every system tool: on one CI host the watches
covered 1,214 files and 277 MiB, and the first build after a boot spent
33.5 s on the check without running the rule.

Those files sit on the sealed system volume, which changes only with the OS
build the key already records and watches. An entry whose resolution stays
on that volume throughout now contributes its name, mode and link target but
not its content, and neither it nor a listing on the volume is watched. An
entry that passes through a link or a directory anywhere else stays watched
and digested, even when it ends on the volume, because that part can change
without an OS update.

On the same host the watches drop to 255 files and 2.4 MiB. On a warm macOS
host, a new server's check of the repository went from 0.24-0.76 s to
0.02-0.03 s. Linux keys are unchanged; every macOS host's key changes once.
@jeffwall-curlewlabs
jeffwall-curlewlabs merged commit 6555bf1 into main Oct 13, 2026
9 checks passed
@jeffwall-curlewlabs
jeffwall-curlewlabs deleted the system-volume-watches branch October 13, 2026 01:42
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