VM aser-slot → sx-page-full: single-call page render, 0.55s warm
Compiler fixes: - Upvalue re-lookup returns own position (uv-index), not parent slot - Spec: cek-call uses (make-env) not (dict) — OCaml Dict≠Env - Bootstrap post-processes transpiler Dict→Env for cek_call VM runtime fixes: - compile_adapter evaluates constant defines (SPECIAL_FORM_NAMES etc.) via execute_module instead of wrapping as NativeFn closures - Native primitives: map-indexed, some, every? - Nil-safe HO forms: map/filter/for-each/some/every? accept nil as empty - expand-components? set in kernel env (not just VM globals) - unwrap_env diagnostic: reports actual type received sx-page-full command: - Single OCaml call: aser-slot body + render-to-html shell - Eliminates two pipe round-trips (was: aser-slot→Python→shell render) - Shell statics (component_defs, CSS, pages_sx) cached in Python, injected into kernel once, referenced by symbol in per-request command - Large blobs use placeholder tokens — Python splices post-render, pipe transfers ~51KB instead of 2MB Performance (warm): - Server total: 0.55s (was ~2s) - aser-slot VM: 0.3s, shell render: 0.01s, pipe: 0.06s - kwargs computation: 0.000s (cached) SX_STANDALONE mode for sx_docs dev (skips fragment fetches). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
12
sx/app.py
12
sx/app.py
@@ -182,11 +182,11 @@ def create_app() -> "Quart":
|
||||
from quart import request, make_response
|
||||
from shared.browser.app.utils.htmx import is_htmx_request
|
||||
from shared.sx.jinja_bridge import get_component_env, _get_request_context
|
||||
from shared.sx.async_eval import async_eval_slot_to_sx
|
||||
from shared.sx.types import Symbol, Keyword
|
||||
from shared.sx.helpers import full_page_sx, oob_page_sx, sx_response
|
||||
from shared.sx.pages import get_page_helpers
|
||||
from shared.sx.page import get_template_context
|
||||
import os
|
||||
|
||||
path = request.path
|
||||
content_ast = [
|
||||
@@ -199,7 +199,15 @@ def create_app() -> "Quart":
|
||||
ctx = _get_request_context()
|
||||
|
||||
try:
|
||||
content_sx = await async_eval_slot_to_sx(content_ast, env, ctx)
|
||||
if os.environ.get("SX_USE_OCAML") == "1":
|
||||
from shared.sx.ocaml_bridge import get_bridge
|
||||
from shared.sx.parser import serialize
|
||||
bridge = await get_bridge()
|
||||
sx_text = serialize(content_ast)
|
||||
content_sx = await bridge.aser_slot(sx_text, ctx={"_helper_service": "sx"})
|
||||
else:
|
||||
from shared.sx.async_eval import async_eval_slot_to_sx
|
||||
content_sx = await async_eval_slot_to_sx(content_ast, env, ctx)
|
||||
except Exception:
|
||||
from shared.browser.app.errors import _sx_error_page
|
||||
html = _sx_error_page("404", "NOT FOUND",
|
||||
|
||||
@@ -212,16 +212,27 @@ async def eval_sx_url(raw_path: str) -> Any:
|
||||
serialize(oob_ast), ctx=ocaml_ctx))
|
||||
return sx_response(content_sx)
|
||||
else:
|
||||
# Full page: single-pass — layout + content in ONE aser_slot
|
||||
# Full page: single OCaml call — aser-slot + shell render
|
||||
full_ast = [
|
||||
Symbol("~shared:layout/app-body"),
|
||||
Keyword("content"), wrapped_ast,
|
||||
]
|
||||
body_sx = SxExpr(await bridge.aser_slot(
|
||||
serialize(full_ast), ctx=ocaml_ctx))
|
||||
page_source = serialize(full_ast)
|
||||
|
||||
# Pre-compute shell kwargs in Python
|
||||
import time as _time
|
||||
_t0 = _time.monotonic()
|
||||
from shared.sx.helpers import _build_shell_kwargs
|
||||
tctx = await get_template_context()
|
||||
return await make_response(
|
||||
await sx_page(tctx, body_sx), 200)
|
||||
_t1 = _time.monotonic()
|
||||
shell_kwargs = await _build_shell_kwargs(tctx, page_source)
|
||||
_t2 = _time.monotonic()
|
||||
html = await bridge.sx_page_full(
|
||||
page_source, shell_kwargs, ctx=ocaml_ctx)
|
||||
_t3 = _time.monotonic()
|
||||
logger.info("[sx-page-full-py] ctx=%.3fs kwargs=%.3fs ocaml=%.3fs total=%.3fs",
|
||||
_t1-_t0, _t2-_t1, _t3-_t2, _t3-_t0)
|
||||
return await make_response(html, 200)
|
||||
else:
|
||||
content_sx = await _eval_slot(wrapped_ast, env, ctx)
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user