sx-http: JIT enabled, signals loaded, recursive dir loading, assoc fix
- Enable lazy JIT in HTTP mode — pre-compile 24 compiler functions at startup - Load spec/signals.sx + web/engine.sx for reactive primitives - Recursive directory loading for subdirectory components (geography/, etc.) - Re-bind native variadic assoc after stdlib.sx overwrites it - Skip test files, plans/, essays/ directories during HTTP load - Homepage aser: 21-38ms warm, Geography aser: 39-87ms warm Remaining: render-to-html JIT gets disabled by <home symbol error on first request (falls back to CEK). ~docs/page component missing for some pages. Fix those for full parity with Quart. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1701,29 +1701,41 @@ let http_mode port =
|
||||
let sx_sx = project_dir ^ "/sx/sx" in
|
||||
let t0 = Unix.gettimeofday () in
|
||||
(* Core spec + adapters.
|
||||
Skip primitives.sx (declarative metadata — all prims are native in OCaml)
|
||||
and types.sx (gradual type system — not needed for rendering). *)
|
||||
Skip: primitives.sx (declarative metadata — all prims native in OCaml),
|
||||
types.sx (gradual types — not needed for rendering),
|
||||
evaluator.sx (SX-level CEK — native evaluator already compiled in).
|
||||
The native CEK evaluator is faster — evaluator.sx adds a second SX-level
|
||||
stepper that's 100x slower. *)
|
||||
let core_files = [
|
||||
spec_base ^ "/parser.sx";
|
||||
spec_base ^ "/render.sx"; spec_base ^ "/evaluator.sx";
|
||||
spec_base ^ "/render.sx";
|
||||
spec_base ^ "/signals.sx";
|
||||
lib_base ^ "/compiler.sx";
|
||||
web_base ^ "/adapter-html.sx"; web_base ^ "/adapter-sx.sx";
|
||||
web_base ^ "/web-forms.sx";
|
||||
web_base ^ "/web-forms.sx"; web_base ^ "/engine.sx";
|
||||
] in
|
||||
http_load_files env core_files;
|
||||
(* Libraries *)
|
||||
(* Files to skip — declarative metadata, not needed for rendering *)
|
||||
let skip_files = ["primitives.sx"; "types.sx"; "boundary.sx";
|
||||
"harness.sx"; "eval-rules.sx"] in
|
||||
let load_dir dir =
|
||||
"harness.sx"; "eval-rules.sx"; "vm-inline.sx"] in
|
||||
let skip_dirs = ["tests"; "test"; "plans"; "essays"; "spec"] in
|
||||
let rec load_dir dir =
|
||||
if Sys.file_exists dir && Sys.is_directory dir then begin
|
||||
let files = Sys.readdir dir in
|
||||
Array.sort String.compare files;
|
||||
let entries = Sys.readdir dir in
|
||||
Array.sort String.compare entries;
|
||||
Array.iter (fun f ->
|
||||
if Filename.check_suffix f ".sx"
|
||||
&& not (List.mem f skip_files)
|
||||
&& not (Filename.check_suffix f ".test.sx") then
|
||||
http_load_files env [dir ^ "/" ^ f]
|
||||
) files
|
||||
let path = dir ^ "/" ^ f in
|
||||
if Sys.is_directory path then begin
|
||||
if not (List.mem f skip_dirs) then
|
||||
load_dir path
|
||||
end
|
||||
else if Filename.check_suffix f ".sx"
|
||||
&& not (List.mem f skip_files)
|
||||
&& not (String.length f > 5 && String.sub f 0 5 = "test-")
|
||||
&& not (Filename.check_suffix f ".test.sx") then
|
||||
http_load_files env [path]
|
||||
) entries
|
||||
end
|
||||
in
|
||||
load_dir lib_base;
|
||||
@@ -1731,6 +1743,57 @@ let http_mode port =
|
||||
load_dir sx_sx;
|
||||
let t1 = Unix.gettimeofday () in
|
||||
Printf.eprintf "[sx-http] All files loaded in %.3fs\n%!" (t1 -. t0);
|
||||
(* Enable lazy JIT — compile lambdas to bytecode on first call *)
|
||||
register_jit_hook env;
|
||||
let jt0 = Unix.gettimeofday () in
|
||||
let count = ref 0 in
|
||||
let compiler_names = [
|
||||
"compile"; "compile-module"; "compile-expr"; "compile-symbol";
|
||||
"compile-dict"; "compile-list"; "compile-if"; "compile-when";
|
||||
"compile-and"; "compile-or"; "compile-begin"; "compile-let";
|
||||
"compile-letrec"; "compile-lambda"; "compile-define"; "compile-set";
|
||||
"compile-quote"; "compile-cond"; "compile-case"; "compile-case-clauses";
|
||||
"compile-thread"; "compile-thread-step"; "compile-defcomp";
|
||||
"compile-defisland"; "compile-defmacro";
|
||||
] in
|
||||
List.iter (fun name ->
|
||||
try
|
||||
match env_get env name with
|
||||
| Lambda l ->
|
||||
l.l_compiled <- Some Sx_vm.jit_failed_sentinel;
|
||||
(match Sx_vm.jit_compile_lambda l (env_to_vm_globals env) with
|
||||
| Some cl -> l.l_compiled <- Some cl; incr count
|
||||
| None -> ())
|
||||
| _ -> ()
|
||||
with _ -> ()
|
||||
) compiler_names;
|
||||
let jt1 = Unix.gettimeofday () in
|
||||
Printf.eprintf "[sx-http] JIT pre-compiled %d compiler fns in %.3fs\n%!" !count (jt1 -. jt0);
|
||||
(* Re-bind native primitives that stdlib.sx may have overwritten with
|
||||
narrower SX versions. The native assoc handles variadic key/value pairs
|
||||
which evaluator.sx requires. *)
|
||||
rebind_host_extensions env;
|
||||
ignore (env_bind env "assoc" (NativeFn ("assoc", fun args ->
|
||||
match args with
|
||||
| Dict d :: rest ->
|
||||
let d2 = Hashtbl.copy d in
|
||||
let rec go = function
|
||||
| [] -> Dict d2
|
||||
| String k :: v :: rest -> Hashtbl.replace d2 k v; go rest
|
||||
| Keyword k :: v :: rest -> Hashtbl.replace d2 k v; go rest
|
||||
| _ -> raise (Eval_error "assoc: pairs")
|
||||
in go rest
|
||||
| _ -> raise (Eval_error "assoc: dict + pairs"))));
|
||||
(* Also re-bind highlight from SX lib if loaded *)
|
||||
(try
|
||||
let hl = env_get env "highlight" in
|
||||
ignore hl (* already bound by lib/highlight.sx *)
|
||||
with _ ->
|
||||
(* Fallback: passthrough highlight *)
|
||||
ignore (env_bind env "highlight" (NativeFn ("highlight", fun args ->
|
||||
match args with
|
||||
| String code :: _ -> SxExpr (Printf.sprintf "(pre :class \"text-sm overflow-x-auto\" (code \"%s\"))" (escape_sx_string code))
|
||||
| _ -> Nil))));
|
||||
(* Inject shell statics *)
|
||||
http_inject_shell_statics env;
|
||||
(* Start TCP server *)
|
||||
|
||||
Reference in New Issue
Block a user