host: enable serving-mode JIT (SX_SERVING_JIT=1), host code excluded

The Datalog/relations saturation is CPU-bound and JITs cleanly: host conformance
271/271 under JIT, 5.4x faster (1m43s -> 19s, same binary); live /tags 2.5s ->
0.76s. loops/host now carries the merged sx-vm-extensions kernel (the JIT engine
+ gate), built into the binary the container bind-mounts.

- docker-compose: SX_SERVING_JIT=1 (default-OFF gate; opt-in here).
- serve.sh: when JIT is on, (jit-exclude! "host/*" "dream-*" "dr/*"). The host app
  + Dream framework MISCOMPILE on first call in the http-listen + cek_run_with_io
  path (map/rest emit wrong CALL_PRIM args -> 500; the JIT->CEK fallback marks the
  fn failed but does NOT recover the failed call). They're IO-bound, so CEK is no
  slower — but the miscompile is a real kernel-JIT bug to fix upstream (see
  plans/HANDOFF-jit-miscompile.md), after which this exclude can be dropped.

Verified live: cold pages 200 (no first-hit 500), relate picker lists candidates,
relate round-trip works, /tags fast, datalog still JITs (78 dl-* compiles).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-28 19:08:22 +00:00
parent 17c7b90834
commit 389cf96838
2 changed files with 15 additions and 0 deletions

View File

@@ -29,6 +29,10 @@ services:
SX_ADMIN_USER: admin SX_ADMIN_USER: admin
SX_ADMIN_PASSWORD: "sx-host-camper-van-2026" SX_ADMIN_PASSWORD: "sx-host-camper-van-2026"
SX_SESSION_SECRET: "ra-host-sess-7c1f9b3e2a8d4056" SX_SESSION_SECRET: "ra-host-sess-7c1f9b3e2a8d4056"
# Serving-mode JIT: bytecode-compile hot SX (esp. the Datalog/relations path)
# on the epoch serving channel. Validated: host conformance 271/271 under JIT,
# 5.4x faster (1m43s -> 19s). Default-OFF gate, opt in here.
SX_SERVING_JIT: "1"
OCAMLRUNPARAM: "b" OCAMLRUNPARAM: "b"
volumes: volumes:
# SX source (hot-reload on container restart) # SX source (hot-reload on container restart)

View File

@@ -99,6 +99,17 @@ EPOCH=1
for M in "${MODULES[@]}"; do for M in "${MODULES[@]}"; do
echo "(epoch $EPOCH)"; echo "(load \"$M\")"; EPOCH=$((EPOCH+1)) echo "(epoch $EPOCH)"; echo "(load \"$M\")"; EPOCH=$((EPOCH+1))
done done
# Serving-mode JIT: exclude the request-path SX (host app + Dream framework) from
# JIT. Those functions miscompile on first call in the http-listen + cek_run_with_io
# path (a map/rest arg bug → 500, then self-heals via CEK fallback — but the first
# hit fails). They're IO-bound anyway, so CEK is no slower. The JIT win is the
# Datalog/relations saturation (dl-*/relations-*), which JITs cleanly and stays on
# (e.g. /tags 2.5s -> 0.76s).
if [ "${SX_SERVING_JIT:-}" = "1" ]; then
echo "(epoch $EPOCH)"
echo "(eval \"(jit-exclude! \\\"host/*\\\" \\\"dream-*\\\" \\\"dr/*\\\")\")"
EPOCH=$((EPOCH+1))
fi
# Point the blog at the DURABLE file backend (persists under $SX_PERSIST_DIR), # Point the blog at the DURABLE file backend (persists under $SX_PERSIST_DIR),
# then idempotently seed a welcome post (sx_content = SX element markup, the # then idempotently seed a welcome post (sx_content = SX element markup, the
# editor's content model). Re-seeding is a no-op if the slug already exists. # editor's content model). Re-seeding is a no-op if the slug already exists.