E ff ect handlers in OCaml KC Sivaramakrishnan 1 & Stephen Dolan 1 Leo White 2 , Jeremy Yallop 1,3 , Armaël Guéneau 4 , Anil Madhavapeddy 1,3 1 2 3 4
Concurrency ≠ Parallelism • Concurrency • Programming technique • Overlapped execution of processes • Parallelism • ( Extreme ) Performance hack • Simultaneous execution of computations Concurrency ∩ Parallelism ➔ Scalable Concurrency ( Fibers ) ( Domains )
Schedulers • Multiplexing fj bers over domain(s) Bake scheduler into the runtime system (GHC) • • Allow programmers to describe schedulers! Parallel search —> LIFO work-stealing • Web-server —> FIFO runqueue • Data parallel —> Gang scheduling • • Algebraic E ff ects and Handlers
Algebraic E ff ects: Example effect Foo : int -> int let f () = (perform (Foo 3)) (* 3 + 1 *) + (perform (Foo 3)) (* 3 + 1 *) let r = try f () with effect (Foo i) k -> continue k (i + 1) val r : int = 8
Dynamic wind let dynamic_wind before_thunk thunk after_thunk = before_thunk (); let res = match thunk () with | v -> v | exception e -> after_thunk (); raise e | effect e k -> after_thunk (); let res' = perform e in before_thunk (); continue k res' in after_thunk (); res
Effect systems and modularity • Right now, we type e ff ects like ML exceptions • (we're in the market for an e ff ect system, if anyone has one lying around...) • We need modularity, because e ff ects can: • be local, dynamic and fresh • be abstracted, renamed and reuse • We don't know statically whether two e ff ects are the same
Scheduler Demo 1 [1] https://github.com/kayceesrk/ocaml15-e ff /tree/master/chameneos-redux
Generator from Iterator 1 type 'a t = | Leaf | Node of 'a t * 'a * 'a t let rec iter f = function | Leaf -> () | Node (l, x, r) -> iter f l; f x; iter f r (* val to_gen : 'a t -> (unit -> 'a option) *) let to_gen (type a) (t : a t) = let module M = struct effect Next : a -> unit end in let open M in let step = ref (fun () -> assert false) in let first_step () = try iter (fun x -> perform (Next x)) t; None with effect (Next v) k -> step := continue k; Some v in step := first_step; fun () -> !step () [1] https://github.com/kayceesrk/ocaml15-e ff /blob/master/generator.ml
Implementation • Fibers: Heap allocated, dynamically resized stacks • ~10s of bytes • No unnecessary closure allocation costs unlike CPS • One-shot delimited continuations • Simpli fj es reasoning about resources - sockets, locks, etc. • Handlers —> Linked-list of fj bers handle / sp continue call chain reference handler
Implementation • Fibers: Heap allocated, dynamically resized stacks • ~10s of bytes • No unnecessary closure allocation costs unlike CPS • One-shot delimited continuations • Simpli fj es reasoning about resources - sockets, locks, etc. • Handlers —> Linked-list of fj bers sp handle / handle / continue continue call chain reference handler
Implementation • Fibers: Heap allocated, dynamically resized stacks • ~10s of bytes • No unnecessary closure allocation costs unlike CPS • One-shot delimited continuations • Simpli fj es reasoning about resources - sockets, locks, etc. • Handlers —> Linked-list of fj bers sp handle / continue call chain perform reference handler
Native-code fj bers — Vanilla C OCaml start program OCaml C call C OCaml callback OCaml C call C OCaml callback OCaml
Native-code fj bers — E ff ects system stack OCaml start program handle C C C call OCaml callback C OCaml heap C call 1. Stack over fm ow checks for OCaml functions • Simple static analysis eliminates many checks 2. FFI calls are more expensive due to stack switching • Specialise for calls which {allocate / pass arguments on stack / do neither}
0.25 0.75 0.5 0 1 ae--add_times_nsec_sum_higher_ sequence-cps ae--04124___why_e36d6b_int-T- ae--04298___why_7ae35b_p4_3_ numal-k-means ae--Automaton_i_part2-B_transla ae--01192___why_98479f_p4_3_ ae--fill_assert_39_Ae- Performance : Vanilla OCaml ae--00076___why_f2468a_Site_ce ae--00344___why_fb54b2_Foncti numal-fft chameneos-async ae--00224___why_c6049d_p9_17- ae--00020___why_bf6246_euler00 ae--00329___why_265778_p4_25 numal-lu-decomposition numal-levinson-durbin ae--08033___why_bebe52_p4_3_ Normalised time (lower is better) numal-rnd_access ae--00145___why_0a8ac0_p9_15 ae--00195___fib__package-T-WP ae--02802___step_function_test__ ae--02362___why_be93d3_p4_3_ cpdf-squeeze E ff ects ~0.9% slower ae--02182___why_3f7a7d_inverse_ ae--01201___flight_manager__pack thread-ring-async-pipe ae--00222___fib__package-T-WP_ chameneos-lwt ae--00893___why_b3d830_euler001 sequence Effects async_echo_merge setrip thread-sleep-async ae--01012___p__package-T-WP_p thread-ring-lwt-mvar setrip-smallbuf numal-qr-decomposition numal-durand-kerner-aberth cpdf-transform valet-async Vanilla lexifi-g2pp almabench numal-naive-multilayer jsontrip-sample async_rpc cohttp-lwt cohttp-async frama-c-idct sauvola-contrast cpdf-reformat chameneos-th minilight valet-lwt menhir-fancy js_of_ocaml menhir-standard bdd numal-simple_access cpdf-merge kb patdiff core_micro kb-no-exc ydump-sample frama-c-deflate menhir-sql ae--00115___why_b6d80d_relabel thread-ring-lwt-stream thread-sleep-lwt chameneos-evtchn
Performance : Chameneos-Redux Lwt Concurrency Monad GHC Fibers 1.8 1.35 Time (S) 0.9 0.45 0 1 2 3 4 5 6 7 8 9 10 Iterations (X100,000)
Performance : Generator Iterator Fiber Generator H/W Generator 4 3 Time (S) 2 1 0 15 16 17 18 19 20 21 22 23 24 25 Binary tree depth
Javascript backend • js_of_ocaml OCaml bytecode —> Javascript • • js_of_ocaml compiler pass • Whole-program selective CPS transformation • Work-in-progress! • Selective CPS translation
fj n. Multicore OCaml: https://github.com/ocamllabs/ocaml-multicore Examples: https://github.com/kayceesrk/ocaml-e ff -example
Recommend
More recommend