Skip to content

Reuse read interfaces across compiler requests in OCaml rewatch - #8874

Open
cknitt wants to merge 1 commit into
masterfrom
ocaml-rewatch-cmi-read-cache
Open

cknitt wants to merge 1 commit into
masterfrom
ocaml-rewatch-cmi-read-cache

Conversation

@cknitt

@cknitt cknitt commented Oct 16, 2026

Copy link
Copy Markdown
Member

With in-process compilation, OCaml rewatch compiles many modules on each worker domain, but every module read again each interface it uses. For the large Stdlib interfaces (Stdlib_Array, Stdlib_String, …), reading and unmarshalling them is a sizable part of compiling a small module.

Bs_cmi_load can now keep the interfaces it has read, per domain. Rewatch turns this on; the standalone bsc doesn't.

  • Per domain, not shared. Copying a signature (Subst) temporarily marks the source types in place, so domains sharing one cached value crash. Within a domain, each copy restores its marks before the next request.
  • Validated by file metadata. An entry is used only while the file's device, inode, size and modification time (from fstat on the descriptor being read) are unchanged.
  • Recently modified files are always read. Published .cmi files are rewritten in place, so on a file system with a coarse clock, a same-size rewrite within one tick would keep all of that metadata. Like Git with racily clean files, an interface modified in the last two seconds is never cached or reused.
  • Bounded. A domain keeps at most 16 MB of interface files (the runtime's are about 1.5 MB) and starts over past that, so long watch sessions don't grow without bound.

Outputs (JS and everything in lib/) are byte-identical to master at 1 and 8 domains. Peak memory is about the same or lower.

Clean builds on a Linux VM:

project domains master this PR
tests/tests (without string_unicode_test) 1 1.27 s 1.20 s
8 0.373 s 0.356 s
synthetic, 1501 modules using Stdlib 1 3.87 s 3.17 s
8 0.913 s 0.696 s

The synthetic project is closer to a real application, whose modules use the standard library throughout.

New test: cmi_read_cache in ounit_compiler_request_tests.ml checks that a just-written interface isn't kept, that an older one is, and that a same-size rewrite with a different modification time is read again.

🤖 Generated with Claude Code

@cknitt
cknitt force-pushed the ocaml-rewatch-cmi-read-cache branch from f8cc3c5 to 5c4deb7 Compare October 16, 2026 05:59
Each module re-read the interfaces it uses, which for the large Stdlib
ones is a sizable part of compiling a small module. Entries are checked
against the file's identity, size and modification time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZbCuRQ1Tn31bnKzLj5e72
Signed-off-by: Christoph Knittel <ck@cca.io>
@cknitt
cknitt force-pushed the ocaml-rewatch-cmi-read-cache branch from 5c4deb7 to 77df19a Compare October 16, 2026 05:59
@cknitt
cknitt marked this pull request as ready for review October 16, 2026 05:59
@codecov

codecov Bot commented Oct 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.03%. Comparing base (dcc7e35) to head (77df19a).

Files with missing lines Patch % Lines
compiler/core/bs_cmi_load.ml 90.47% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #8874      +/-   ##
==========================================
+ Coverage   81.02%   81.03%   +0.01%     
==========================================
  Files         453      453              
  Lines       63030    63069      +39     
==========================================
+ Hits        51070    51108      +38     
- Misses      11960    11961       +1     
Files with missing lines Coverage Δ
tests/ounit_tests/ounit_compiler_request_tests.ml 97.72% <100.00%> (+0.04%) ⬆️
compiler/core/bs_cmi_load.ml 84.21% <90.47%> (+6.43%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pkg-pr-new

pkg-pr-new Bot commented Oct 16, 2026

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8874

@rescript/belt

npm i https://pkg.pr.new/@rescript/belt@8874

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@8874

@rescript/darwin-x64

npm i https://pkg.pr.new/@rescript/darwin-x64@8874

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@8874

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@8874

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8874

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@8874

commit: 77df19a

@github-actions

Copy link
Copy Markdown

This branch has not been deployed

No deployments
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