Skip to content

Compile in-process on OCaml domains in OCaml rewatch - #8781

Draft
cknitt wants to merge 19 commits into
rewatch-ocaml-portfrom
rewatch-ocaml-in-process
Draft

cknitt wants to merge 19 commits into
rewatch-ocaml-portfrom
rewatch-ocaml-in-process

Conversation

@cknitt

@cknitt cknitt commented Oct 10, 2026 •

Copy link
Copy Markdown
Member

Stacked on #8780.

This PR moves compilation into the OCaml rewatch process. Instead of starting bsc for every parse and compile, rescript links the compiler and runs requests on a bounded pool of OCaml 5 domains. That removes process start-up and pipe handling, which make the subprocess port about 6% slower than Rust on clean builds. It also opens the door to sharing compiler state between requests later.

Changes

  • The compiler's process-wide mutable state is made request-scoped. Clflags, Js_config, warnings, environment and CRC caches, predefined types, Ident stamps, printers, diagnostics and backend caches move into domain-local state. Almost all of it lives in Request_local keys: every request starts with fresh values, as a new bsc process would, and the previous values are restored afterwards. Only Ident stamps, the request context, output capture and the order-sensitive predefined types keep explicit handling. The driver moves from rescript_compiler_main.ml to rescript_compiler_driver.ml, so bsc and rewatch share it.
  • Each request's compiler output goes to request-owned buffers, written in text mode so that Windows output keeps bsc's CRLF line endings.
  • Rewatch schedules independent parse and compile requests on worker domains. By default that's at most 8, and one fewer than the CPU count; REWATCH_COMPILER_DOMAINS overrides it. Artifact publication stays on the scheduling domain. PPXs and hooks still run as external processes.
  • rescript format also runs on the embedded compiler. PPXs, js-post-build, --after-build and the lock-owner check are the only remaining subprocesses. RESCRIPT_BSC_EXE now only affects rescript-rust, and CONTRIBUTING.md says how to test a local compiler instead.
  • lib/bs/compiler-info.json still records the bsc.exe shipped next to rescript.exe. The VS Code extension reads bsc_path to find bsc.exe and the other platform binaries.

Known issues before this can leave draft

  • An earlier domain build once produced a differing output that was never explained. Review since found and fixed shared or leaked state:

    • Js_analyzer's free-variable accumulator was shared between domains, so Js_shake could drop a live function definition; this reproduced once in CI;
    • Parmatch.Conv's name counter, Ctype's abbreviation memo and levels, PPX cookies and the parser hooks for error messages.

    An audit of top-level mutable records, visitors and tables found no other live case. Regression tests cover the Js_analyzer race and the leaked Ctype memo.

  • No ThreadSanitizer run over a parallel build yet.

  • bsc now buffers its output until exit. Diagnostics no longer stream, and warnings already emitted are lost if an internal compiler error escapes.

  • The focused suite's slow-compiler cases no longer apply; signal handling is covered through a slow js-post-build hook instead.

Tests

tests/rewatch_ounit_tests/compiler_driver_tests.ml checks that each kind of request-scoped state is isolated between consecutive and concurrent requests. rewatch-ocaml/bench compares clean-build artifacts across domain counts; it does not run in CI.

🤖 Generated with Claude Code

@cknitt
cknitt added this pull request to stack #8782 October 10, 2026 16:36
@codecov

codecov Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.22042% with 341 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.74%. Comparing base (03d9bf4) to head (0d1e9f7).
⚠️ Report is 6 commits behind head on rewatch-ocaml-port.

Files with missing lines Patch % Lines
compiler/bsc/rescript_compiler_driver.ml 73.16% 73 Missing ⚠️
compiler/ml/ctype.ml 81.99% 47 Missing ⚠️
compiler/ml/printtyp.ml 60.34% 46 Missing ⚠️
compiler/gentype/debug.ml 51.21% 20 Missing ⚠️
compiler/ml/env.ml 84.34% 18 Missing ⚠️
compiler/ext/compiler_request_output.ml 77.77% 10 Missing ⚠️
compiler/ml/typecore.ml 91.73% 10 Missing ⚠️
compiler/core/js_implementation.ml 79.06% 9 Missing ⚠️
compiler/ml/cmi_format.ml 50.00% 8 Missing ⚠️
compiler/ml/ast_mapper.ml 53.33% 7 Missing ⚠️
... and 50 more
Additional details and impacted files
@@                  Coverage Diff                   @@
##           rewatch-ocaml-port    #8781      +/-   ##
======================================================
+ Coverage               80.66%   80.74%   +0.07%     
======================================================
  Files                     463      468       +5     
  Lines                   62792    63575     +783     
======================================================
+ Hits                    50651    51331     +680     
- Misses                  12141    12244     +103     
Files with missing lines Coverage Δ
analysis/src/module_resolution.ml 18.18% <100.00%> (ø)
compiler/common/js_config.ml 81.81% <100.00%> (+6.81%) ⬆️
compiler/core/bs_conditional_initial.ml 100.00% <100.00%> (ø)
compiler/core/cmd_ppx_apply.ml 77.96% <100.00%> (+0.77%) ⬆️
compiler/core/config_util.ml 93.75% <100.00%> (-6.25%) ⬇️
compiler/core/ir_diagnostics.ml 92.59% <100.00%> (ø)
compiler/core/js_analyzer.ml 82.91% <100.00%> (-0.32%) ⬇️
compiler/core/js_cmj_format.ml 94.54% <100.00%> (+0.20%) ⬆️
compiler/core/js_dump.ml 92.84% <100.00%> (+<0.01%) ⬆️
compiler/core/js_dump_program.ml 98.33% <100.00%> (ø)
... and 103 more
🚀 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.

@cknitt
cknitt force-pushed the rewatch-ocaml-in-process branch from 2cb5e55 to 236cf9b Compare October 10, 2026 17:56
cknitt and others added 6 commits October 10, 2026 18:59
Signed-off-by: Christoph Knittel <ck@cca.io>
Signed-off-by: Christoph Knittel <ck@cca.io>
compiler-info.json records the bundled bsc.exe again, which editor tooling
uses to find the platform binaries. RESCRIPT_BSC_EXE only affects Rust.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Concurrent requests shared the counter and could reuse a name within one
exhaustiveness check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Ctype's abbreviation memos and levels, and PPX cookies, now start fresh for
each request. Parser hooks are installed once; Typetexp's unused pre_univars
is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
@cknitt
cknitt force-pushed the rewatch-ocaml-in-process branch from 236cf9b to 3de8d08 Compare October 10, 2026 18:59
cknitt and others added 6 commits October 10, 2026 20:24
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
The formatter emits CRLF on Windows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
On Windows this gives the same CRLF line endings as a bsc process.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
@pkg-pr-new

pkg-pr-new Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

rescript

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

@rescript/belt

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

@rescript/darwin-arm64

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

@rescript/darwin-x64

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

@rescript/linux-arm64

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

@rescript/linux-x64

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

@rescript/runtime

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

@rescript/win32-x64

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

commit: 2fff740

cknitt and others added 7 commits October 11, 2026 05:18
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Concurrent requests mixed their sets, so Js_shake could drop a live
function definition.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Not reached concurrently today; same pattern as the Js_analyzer race.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Windows rejects locking an unbounded range.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
Request_local keys get a fresh value per request and are restored after it,
replacing the per-module with_fresh and reset functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>
macOS can deliver both edits in one batch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Christoph Knittel <ck@cca.io>

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