(* Parallel Nock Execution - Multi-Domain Nock for Multi-Core Urbit! * * This is THE breakthrough: Running Nock across multiple CPU cores! * * Strategies: * 1. Parallel batch execution - run multiple Nock computations in parallel * 2. Parallel scry - read-only queries across domains * 3. Future: Fork/join within a single Nock computation *) (* Parallel execution result *) type 'a result = | Success of 'a | Error of string (* Execute multiple Nock computations in parallel * * Takes a list of (subject, formula) pairs and executes them * in parallel across the domain pool. * * This is perfect for: * - Batch scry requests * - Multiple independent pokes * - Parallel jet execution *) let parallel_batch pool computations = let execute_one (subject, formula) = try let result = Nock.nock_on subject formula in Success result with | e -> Error (Printexc.to_string e) in Domain_pool.parallel_map pool execute_one computations (* Execute multiple Nock computations using parallel_for * * More efficient for large batches as it uses chunking *) let parallel_batch_indexed pool subjects formulas = let num_tasks = min (List.length subjects) (List.length formulas) in let results = Domain_pool.parallel_for pool ~start:0 ~finish:(num_tasks - 1) ~body:(fun i -> let subject = List.nth subjects i in let formula = List.nth formulas i in try Success (Nock.nock_on subject formula) with | e -> Error (Printexc.to_string e) ) in results (* Parallel scry - execute read-only queries in parallel * * This is incredibly powerful for serving many simultaneous queries! * C Vere can only do one at a time, we can do hundreds simultaneously! *) let parallel_scry pool state queries = let execute_query query = try (* In a real implementation, this would use State.peek *) (* For now, we just run Nock on the state *) let result = Nock.nock_on state query in Success result with | e -> Error (Printexc.to_string e) in Domain_pool.parallel_map pool execute_query queries (* Map-reduce style parallel Nock * * Execute Nock on each item in parallel, then reduce results *) let parallel_map_reduce pool ~subjects ~formula ~reduce ~init = (* Execute Nock in parallel *) let execute_one subject = try Success (Nock.nock_on subject formula) with | e -> Error (Printexc.to_string e) in let results = Domain_pool.parallel_map pool execute_one subjects in (* Reduce results *) List.fold_left (fun acc result -> match result with | Success noun -> reduce acc noun | Error _ -> acc ) init results (* Async execution - non-blocking Nock * * Execute Nock asynchronously and return a promise *) let async_nock pool subject formula = Domain_pool.async pool (fun () -> try Success (Nock.nock_on subject formula) with | e -> Error (Printexc.to_string e) ) (* Wait for async result *) let await_result = Domain_pool.await (* Benchmark result type *) type benchmark_result = { count: int; sequential_time: float; parallel_time: float; speedup: float; results_match: bool; } (* Parallel increment benchmark * * Useful for testing parallel speedup *) let parallel_increment_bench pool count = let subjects = List.init count (fun i -> Noun.atom i) in (* Formula: [4 0 1] (increment subject) *) let formula = Noun.cell (Noun.atom 4) (Noun.cell (Noun.atom 0) (Noun.atom 1)) in let start = Unix.gettimeofday () in let results = List.map (fun subject -> Nock.nock_on subject formula ) subjects in let sequential_time = Unix.gettimeofday () -. start in let start = Unix.gettimeofday () in let parallel_results_wrapped = Domain_pool.parallel_map pool (fun subject -> try Success (Nock.nock_on subject formula) with e -> Error (Printexc.to_string e) ) subjects in let parallel_time = Unix.gettimeofday () -. start in (* Extract successful results for comparison *) let parallel_results = List.filter_map (function | Success n -> Some n | Error _ -> None ) parallel_results_wrapped in let speedup = sequential_time /. parallel_time in { count; sequential_time; parallel_time; speedup; results_match = (results = parallel_results); } (* Get parallel execution statistics *) let stats pool = Domain_pool.stats pool