Effective I/O an unpromising approach to systems programming - - PowerPoint PPT Presentation

effective i o
SMART_READER_LITE
LIVE PREVIEW

Effective I/O an unpromising approach to systems programming - - PowerPoint PPT Presentation

Effective I/O an unpromising approach to systems programming Stephen Dolan KC Sivaramakrishnan OCaml Labs Effect handlers let do_stuff x = if x.is_bad then log oh no; process x 2 Effect handlers let do_stuff x = if x.is_bad then


slide-1
SLIDE 1

Effective I/O

Stephen Dolan KC Sivaramakrishnan OCaml Labs

an unpromising approach to systems programming

slide-2
SLIDE 2

2

Effect handlers

let do_stuff x = if x.is_bad then log “oh no”; process x

slide-3
SLIDE 3

3

Effect handlers

let do_stuff x = if x.is_bad then raise PrettyBad; process x match ... with | result -> result | exception PrettyBad -> log “it's pretty bad”; exit 1

slide-4
SLIDE 4

4

Effect handlers

let do_stuff x = if x.is_bad then raise PrettyBad; process x match ... with | result -> result | exception PrettyBad -> (* wish it kept going *)

slide-5
SLIDE 5

5

Effect handlers

let do_stuff x = if x.is_bad then raise PrettyBad; process x match ... with | result -> result | exception PrettyBad -> continue

slide-6
SLIDE 6

6

Effect handlers

let do_stuff x = if x.is_bad then perform PrettyBad; process x match ... with | result -> result | effect PrettyBad k -> continue k

slide-7
SLIDE 7

7

Scheduling tasks

let run_q = Queue.create () let enqueue k = Queue.push k run_q let rec dequeue () = if Queue.is_empty run_q then () else continue (Queue.pop run_q) ()

slide-8
SLIDE 8

8

Scheduling tasks

effect Yield : unit effect Fork : (unit -> unit) -> unit let rec schedule f = match f () with | () -> dequeue () | effect Yield k -> enqueue k; dequeue () | effect (Fork f) k -> enqueue k; schedule f

slide-9
SLIDE 9

9

Direct-style I/O

let copy_channels = let buf_len = 65536 in let buf = Bytes.create buf_len in let rec loop ic oc = match input ic buf 0 buf_len with | 0 -> () | n -> output oc buf 0 n; loop ic oc in loop

slide-10
SLIDE 10

10

An effective stdlib

type in_channel = Reader.t effect Input : in_channel * bytes * int * int

  • > int

let input ic buf pos len = perform (Input (ic, buf, pos, len))

slide-11
SLIDE 11

11

Direct-style with Async

val run : (unit -> 'a) -> 'a Deferred.t let run f = match f () with | x -> return x | effect (Input (ic, buf, pos, len)) k -> Reader.read ic buf ~pos ~len >>= fun x -> continue k x

slide-12
SLIDE 12

12

Direct-style I/O

  • Simple I/O interfaces use direct calls
  • Effjcient ones use callbacks, for overlapping
  • With effects, we can write the simple code but

run the fast code

slide-13
SLIDE 13

13

Mixing styles

  • Effects let us mix direct and monadic code
  • Parts of the code can choose whether they

need to control scheduler interactions

  • Libraries can expose code without imposing a

particular I/O style

slide-14
SLIDE 14

14

Managing resources

let file = open_in “words.txt” in match parse_contents file with | result -> close file; result | exception e -> close file; raise e

slide-15
SLIDE 15

15

Managing resources

  • Computations holding resources are linear

– so their continuations are too!

  • Linear continuations are very, very fast
  • Lacking linear types, we fake them dynamically
slide-16
SLIDE 16

16

Blocking I/O

  • The operating system provides select(),

telling us whether I/O will block

  • But it lies, and it lies, and it lies.
  • Async uses thread pools to deal with this
slide-17
SLIDE 17

17

Thread pools vs. effects

  • For operations which happen not to block,

thread pools have high overhead

  • With effects, we don't have to decide in advance

whether to switch to another thread

  • We can invoke continuations on any C thread
slide-18
SLIDE 18

18

Overlapping with effects

| effect (Delayed id) k -> Hashtbl.add ongoing_io id k | effect (Completed id) k -> let k’ = Hashtbl.find ongoing_io id in Hashtbl.remove ongoing_io id; enqueue (fun () -> continue k ()); continue k’ ()

slide-19
SLIDE 19

19

Questions?