Lwt: a Cooperative Thread Library Jrme Vouillon Universite Paris - - PowerPoint PPT Presentation

lwt a cooperative thread library
SMART_READER_LITE
LIVE PREVIEW

Lwt: a Cooperative Thread Library Jrme Vouillon Universite Paris - - PowerPoint PPT Presentation

Lwt: a Cooperative Thread Library Jrme Vouillon Universite Paris Diderot - Paris 7, CNRS Introduction Library Lwt Cooperative threads Entirely written in Ocaml Monadic Motivation : race conditions Less opportunities for race


slide-1
SLIDE 1

Lwt: a Cooperative Thread Library

Jérôme Vouillon Universite Paris Diderot - Paris 7, CNRS

slide-2
SLIDE 2

Introduction

Library Lwt

  • Cooperative threads
  • Entirely written in Ocaml
  • Monadic
slide-3
SLIDE 3

Motivation : race conditions

Less opportunities for race conditions Explicit context switches Large portions of code executed atomically Modules Hashtbl, Str are thread-safe

slide-4
SLIDE 4

Motivation : performance

Lightweight threads Can use thousands of them Context switches are cheap Just a few function calls

slide-5
SLIDE 5

Introduction to the library

slide-6
SLIDE 6

Promises

Synchronous functions

input_char : in_channel -> char Unix.sleep : int -> unit

Asynchronous functions

Lwt_chan.input_char : in_channel -> char t Lwt_unix.sleep : int -> unit t

Promise: proxy for an eventual value

slide-7
SLIDE 7

Combining promises

Asynchronous wait

Promise p : ’a t Function f : ’a -> ’b t ⇒ result v : ’b t

slide-8
SLIDE 8

Combining promises

Asynchronous wait

Promise p : ’a t Function f : ’a -> ’b t ⇒ result v : ’b t

bind : ’a t -> (’a -> ’b t) -> ’b t

slide-9
SLIDE 9

Combining promises

Asynchronous wait

Promise p : ’a t Function f : ’a -> ’b t ⇒ result v : ’b t

bind : ’a t -> (’a -> ’b t) -> ’b t

Trivial promise

return : ’a -> ’a t

slide-10
SLIDE 10

Combining promises

Asynchronous wait

Promise p : ’a t Function f : ’a -> ’b t ⇒ result v : ’b t

bind : ’a t -> (’a -> ’b t) -> ’b t

Trivial promise

return : ’a -> ’a t

⇒ this is a monad

slide-11
SLIDE 11

A first example

Sequential code

let forward in_fd out_fd buffer = let n = Unix.read in_fd buffer 0 1024 in Unix.sleep 3; let n’ = Unix.write out_fd buffer 0 n in ()

Asynchronous code

let forward in_fd out_fd buffer = Lwt.bind (Lwt_unix.read in_fd buffer 0 1024) (fun n -> Lwt.bind (Lwt_unix.sleep 3) (fun () -> Lwt.bind (Lwt_unix.write out_fd buffer 0 n) (fun n’ -> Lwt.return ())))

slide-12
SLIDE 12

Improved syntax

Asynchronous code

let forward in_fd out_fd buffer = Lwt.bind (Lwt_unix.read in_fd buffer 0 1024) (fun n -> Lwt.bind (Lwt_unix.sleep 3) (fun () -> Lwt.bind (Lwt_unix.write out_fd buffer 0 n) (fun n’ -> Lwt.return ())))

Asynchronous code, improved syntax

let forward in_fd out_fd buffer = Lwt_unix.read in_fd buffer 0 1024 >>= fun n -> Lwt_unix.sleep 3 >>= fun () -> Lwt_unix.write out_fd buffer 0 n >>= fun n’ -> Lwt.return ()

slide-13
SLIDE 13

Core of the library

slide-14
SLIDE 14

The Lwt module

Core module Lwt

type ’a t val return : ’a -> ’a t val bind : ’a t -> (’a -> ’b t) -> ’b t val fail : exn -> ’a t val catch : (unit -> ’a t) -> (exn -> ’a t) -> ’a t val wait : unit -> ’a t val wakeup : ’a t -> ’a -> unit val wakeup_exn : ’a t -> exn -> unit val poll : ’a t -> ’a option

slide-15
SLIDE 15

Dealing with exceptions

Raising an exception

fail : exn -> ’a t

Catching exceptions

catch : (unit -> ’a t) -> (exn -> ’a t) -> ’a t

slide-16
SLIDE 16

Regular exceptions

Regular exception are also caught

Lwt.catch (fun () -> raise Exit) (fun e -> Lwt.return ())

... even when they do not happen immediately

Lwt.catch (fun () -> Lwt_unix.sleep 3 >>= fun () -> raise Exit) (fun e -> Lwt.return ())

slide-17
SLIDE 17

Low-level primitives

A promise with no value yet

wait : unit -> ’a t

Assigning a value to a promise

wakeup : ’a t -> ’a -> unit wakeup_exn : ’a t -> ’a -> unit

Current state of a promise

poll : ’a t -> ’a option

slide-18
SLIDE 18

Structure of the library

Lwt

Core library

Lwt_unix

Unix system calls, scheduler

Lwt_chan

Buffered I/O

Lwt_mutex

Mutual exclusion locks

Lwt_timeout

Manage timers (for instance, for closing idle network connections)

Lwt_preemptive

Execute functions

  • n preemptive threads
slide-19
SLIDE 19

Using the library

slide-20
SLIDE 20

A simple scheduler (1/2)

Queue of suspended threads

let queue = Queue.create ()

Yield function

let yield () = let res = Lwt.wait () in Queue.push res queue; res

slide-21
SLIDE 21

A simple scheduler (2/2)

Scheduler

let rec run () = match try Some (Queue.take queue) with Queue.Empty -> None with None

  • > ()

| Some t -> Lwt.wakeup t (); run ()

slide-22
SLIDE 22

Using the scheduler

let rec loop message n = if n > 0 then begin yield () >>= fun () -> Format.printf "%s@." message; loop message (n - 1) end else Lwt.return () let ta = loop "a" 6 in let tb = loop "b" 5 in run ()

slide-23
SLIDE 23

Implementation

slide-24
SLIDE 24

Promises

The type of promises (simplified)

type ’a t = { mutable state : ’a state } and ’a state = Return of ’a | Sleep of (unit -> unit) list

Creating promises

let return v = { state = Return v } let wait () = { state = Sleep [] }

slide-25
SLIDE 25

Thread termination

Fulfilling a promise

let wakeup p v = match p.state with Sleep waiters -> p.state <- Return v; List.iter (fun f -> f ()) waiters | Return _ -> invalid_arg "wakeup"

slide-26
SLIDE 26

Synchronization (1/2)

let rec bind p f = match p.state with Return v -> f v | Sleep waiters -> let result = wait () in let restart () = connect result (bind p f) in p.state <- Sleep (restart :: waiters); result

slide-27
SLIDE 27

Synchronization (2/2)

let rec connect p p’ = match p’.state with Return v -> wakeup p v | Sleep waiters’ -> let restart () = connect p p’ in p’.state <- Sleep (restart :: waiters’)

slide-28
SLIDE 28

Actual implementation : exceptions

Exceptions

type ’a state = ... | Fail of exn

slide-29
SLIDE 29

Actual implementation : memory-leaks

Avoiding memory leaks Union-find datastructure

type ’a state = ... | Link of ’a t

slide-30
SLIDE 30

Performances

slide-31
SLIDE 31

Performances

From the Computer Language Shoutout Benchmarks Haskell Lwt System threads thread-ring 5.5 5.5 34.0 chameneos-redux 4.3 14.9 430 Mostly measure context-switches costs...

slide-32
SLIDE 32

Related works

CPS-based threads

  • A poor man’s concurrency monad, Claessen, 1999
  • Combining Events and Threads for Scalable Network

Services, Li and Zdancewic, 2007

  • An ocaml-based network services platform, Waterson,

2007

  • F#’s asynchronous workflows, Syme, 2007

Based on a monad of suspended computations

slide-33
SLIDE 33

Applications

Successfully used in real-world applications

  • Unison file synchronizer (since 2002)
  • Ocsigen Web server
slide-34
SLIDE 34

Download

Available at: http://www.ocsigen.org/lwt