# HG changeset patch # User Malcolm Matalka # Date 1563779076 -7200 # Mon Jul 22 09:04:36 2019 +0200 # Node ID 4e4ad59fb00405831a5eac6b4f4617a9a8eebd81 # Parent 7a0b97c6738f38f25e8a343f3df07f62599ddc25 ADD Latest state diff --git a/.hgignore b/.hgignore --- a/.hgignore +++ b/.hgignore @@ -7,4 +7,8 @@ presentation/byocm.nav presentation/byocm.out presentation/byocm.pdf -presentation/byocm.toc \ No newline at end of file +presentation/byocm.toc + +code/build/ +code/pds.mk +code/Ocamlrules.mk.in \ No newline at end of file diff --git a/Makefile b/Makefile --- a/Makefile +++ b/Makefile @@ -1,6 +1,12 @@ -.PHONY: all presentation +.PHONY: all presentation code test -all: presentation +all: presentation code presentation: $(MAKE) -C presentation + +code: + $(MAKE) -C code + +test: code + $(MAKE) -C code test diff --git a/code/Makefile b/code/Makefile new file mode 100644 --- /dev/null +++ b/code/Makefile @@ -0,0 +1,9 @@ +.PHONY: + +all: + pds + $(MAKE) -f pds.mk all + +%: + pds + $(MAKE) -f pds.mk $* diff --git a/code/pds.conf b/code/pds.conf new file mode 100644 --- /dev/null +++ b/code/pds.conf @@ -0,0 +1,26 @@ +[global] +selector = ["opam", "config", "var", "os"] + +[global.release] +extra_compiler_opts = "-bin-annot -strict-sequence -strict-formats -safe-string -noassert" + +[global.debug] +extra_compiler_opts = "-g -bin-annot -strict-sequence -strict-formats -safe-string -w '@d@f@p@u@s@40'" + +[global.profile] +extra_compiler_opts = "-safe-string" + +[global.test-release] +extra_compiler_opts = "-safe-string" + +[global.test-debug] +extra_compiler_opts = "-safe-string" + +[global.test-profile] +extra_compiler_opts = "-safe-string" + +[src.byocm_fut] +install = false + +[tests.byocm_fut] +deps = [ "byocm_fut" ] \ No newline at end of file diff --git a/code/src/byocm_fut/byocm_fut.ml b/code/src/byocm_fut/byocm_fut.ml new file mode 100644 --- /dev/null +++ b/code/src/byocm_fut/byocm_fut.ml @@ -0,0 +1,53 @@ +type +'a t + +type 'a u = { mutable state : 'a state } +and 'a state = [ `Det of 'a + | `Undet of 'a undet + | `Alias of 'a u + ] +and 'a undet = { mutable watchers : ('a -> unit) list } + +external t_of_u : 'a u -> 'a t = "%identity" +external u_of_t : 'a t -> 'a u = "%identity" + +module Promise = struct + type 'a fut = 'a t + type 'a t = 'a fut + let create () = t_of_u { state = `Undet { watchers = [] } } + external future : 'a t -> 'a fut = "%identity" + let set t v = + let u = u_of_t t in + match u with + | { state = `Undet { watchers = watchers } } -> + u.state <- `Det v; + List.iter (fun w -> w v) watchers + | { state = `Det _ } + | { state = `Alias _ } -> + assert false +end + +let rec collapse_alias = function + | { state = `Alias u } -> collapse_alias u + | u -> u + +let return v = t_of_u { state = `Det v } +let bind t f = + let u = collapse_alias (u_of_t t) in + match u with + | { state = `Det v } -> + f v + | { state = `Undet { watchers = watchers } } -> + failwith "nyi" + | { state = `Alias _ } -> + assert false + +let state t = + let u = collapse_alias (u_of_t t) in + match u with + | { state = `Det v } -> `Det v + | { state = `Undet _ } -> `Undet + | { state = `Alias _ } -> assert false + +module Infix_monad = struct + let (>>=) = bind +end diff --git a/code/src/byocm_fut/byocm_fut.mli b/code/src/byocm_fut/byocm_fut.mli new file mode 100644 --- /dev/null +++ b/code/src/byocm_fut/byocm_fut.mli @@ -0,0 +1,17 @@ +type +'a t + +module Promise : sig + type 'a fut = 'a t + type 'a t + val create : unit -> 'a t + val future : 'a t -> 'a fut + val set : 'a t -> 'a -> unit +end + +val return : 'a -> 'a t +val bind : 'a t -> ('a -> 'b t) -> 'b t +val state : 'a t -> [ `Det of 'a | `Undet ] + +module Infix_monad : sig + val (>>=) : 'a t -> ('a -> 'b t) -> 'b t +end diff --git a/code/tests/byocm_fut/test.ml b/code/tests/byocm_fut/test.ml new file mode 100644 --- /dev/null +++ b/code/tests/byocm_fut/test.ml @@ -0,0 +1,31 @@ +let test1 () = + let fut = Byocm_fut.return "hello" in + let res = Byocm_fut.bind fut (fun s -> Byocm_fut.return (s ^ " world")) in + assert (Byocm_fut.state res = `Det "hello world") + +let test2 () = + let open Byocm_fut.Infix_monad in + let res = + Byocm_fut.return "hello" + >>= fun s -> + Byocm_fut.return (s ^ " world") + in + assert (Byocm_fut.state res = `Det "hello world") + +let test3 () = + let open Byocm_fut.Infix_monad in + let p = Byocm_fut.Promise.create () in + let fut = Byocm_fut.Promise.future p in + let res = + fut + >>= fun s -> + Byocm_fut.return (s ^ " world") + in + assert (Byocm_fut.state res = `Undet); + Byocm_fut.Promise.set p "hello"; + assert (Byocm_fut.state res = `Det "hello world") + +let () = + test1 (); + test2 (); + test3 () diff --git a/presentation/byocm.tex b/presentation/byocm.tex --- a/presentation/byocm.tex +++ b/presentation/byocm.tex @@ -1,5 +1,27 @@ \documentclass{beamer} \usepackage{hyperref} +\usepackage{color} +\usepackage{alltt} +\usepackage[T1]{fontenc} +\usepackage[latin1]{inputenc} + +% highlight theme: Kwrite Editor +\newcommand{\hlstd}[1]{\textcolor[rgb]{0,0,0}{#1}} +\newcommand{\hlnum}[1]{\textcolor[rgb]{0.69,0.49,0}{#1}} +\newcommand{\hlesc}[1]{\textcolor[rgb]{1,0,1}{#1}} +\newcommand{\hlstr}[1]{\textcolor[rgb]{0.75,0.01,0.01}{#1}} +\newcommand{\hlpps}[1]{\textcolor[rgb]{0.51,0.51,0}{#1}} +\newcommand{\hlslc}[1]{\textcolor[rgb]{0.51,0.51,0.51}{\it{#1}}} +\newcommand{\hlcom}[1]{\textcolor[rgb]{0.51,0.51,0.51}{\it{#1}}} +\newcommand{\hlppc}[1]{\textcolor[rgb]{0,0.51,0}{#1}} +\newcommand{\hlopt}[1]{\textcolor[rgb]{0,0,0}{#1}} +\newcommand{\hlipl}[1]{\textcolor[rgb]{0,0.34,0.68}{#1}} +\newcommand{\hllin}[1]{\textcolor[rgb]{0.33,0.33,0.33}{#1}} +\newcommand{\hlkwa}[1]{\textcolor[rgb]{0,0,0}{\bf{#1}}} +\newcommand{\hlkwb}[1]{\textcolor[rgb]{0,0.34,0.68}{#1}} +\newcommand{\hlkwc}[1]{\textcolor[rgb]{0,0,0}{\bf{#1}}} +\newcommand{\hlkwd}[1]{\textcolor[rgb]{0,0,0.51}{#1}} +\definecolor{bgcolor}{rgb}{0.88,0.92,0.93} \usetheme{metropolis} \title{Build Your Own Concurrency Monad} @@ -9,13 +31,183 @@ \begin{document} \maketitle -\begin{frame}{This} - \begin{enumerate} - \item Foo bar - \end{enumerate} +\section{Background} + +\begin{frame}{The Problem} + We want to maximize the number of I/O bound operations a single machine can + perform with a programming model people can understand. +\end{frame} + +\begin{frame}{Why do we want a Concurrency Monad?} + \begin{itemize} + \item C10K problem. + \item Code was historically written to be synchronous. + \item OS threads were a transition step but didn't scale. + \end{itemize} +\end{frame} + +\begin{frame}{OS Threads (Synchronous)} + \begin{itemize} + \item Makes concurrency the problem of the OS. + \item Seems like a nice abstraction: I don't really need to change my + synchronous code that much. + \item OS threads are very heavy, they are really meant to utilize all cores. + Good for CPU-bound tasks. + \item Expensive to switch between, user space \( \rightarrow \) kernel space \( + \rightarrow \) user space. + \item With lots of concurrency, we spend all our time context switching. + \end{itemize} +\end{frame} + +\begin{frame}{In User Space (Asynchronous)} + \begin{itemize} + \item Handle multiple connections in a single thread. + \item Use OS APIs to get a list of events, process them, ask again (fewer + context switches). + \item Event Loop. + \item Basic model the same across OS's but specific API calls change. + \item Go, Erlang, Mozart/Oz do this for you. Async/Await in Rust, C\#, and + JavaScript do a similar thing. + \item In Ocaml we can do this as a library, no need to spend 3 years in + language standards meetings! + \end{itemize} +\end{frame} + +\begin{frame}{Anatomy of Concurrency In User Space} + \begin{itemize} + \item The game is to turn kernel calls that can wait an unbounded amount of + time into two calls: One where you tell the kernel to do something and + another when it tells you when it's done. + \item Start the event loop with some initial work. + \item Perform a bit of user-space work then give control back to the event + loop. + \end{itemize} +\end{frame} + +\begin{frame}{Anatomy of Concurrency In User Space} + \center{\includegraphics[scale=0.4]{images/event_loop.png}} +\end{frame} + +\begin{frame}{Comparing Synchronous \& Asynchronous} + \begin{columns}[T] + \begin{column}{0.5\textwidth} + \begin{block}{\underline{Semantically}} + \begin{itemize} + \item Function: \emph{slow\_echo} + \item Read from socket. + \item Wait 1 second. + \item Write text back to socket. + \end{itemize} + \end{block} + \end{column} + \begin{column}{0.5\textwidth} + \begin{block}{\underline{Synchronous}} + \center{\includegraphics[scale=0.3]{images/slow_echo_sync.png}} + \end{block} + \end{column} + \end{columns} \end{frame} -\section{Foobar} +\begin{frame}{Comparing Synchronous \& Asynchronous} + \begin{columns}[T] + \begin{column}{0.5\textwidth} + \begin{block}{\underline{Synchronous}} + \center{\includegraphics[scale=0.3]{images/slow_echo_sync.png}} + \end{block} + \end{column} + \begin{column}{0.5\textwidth} + \begin{block}{\underline{Asynchronous}} + \center{\includegraphics[scale=0.3]{images/slow_echo_event_loop.png}} + \end{block} + \end{column} + \end{columns} +\end{frame} + +\begin{frame}{Comparing Synchronous \& Asynchronous} + \begin{block}{\underline{Synchronous}} + \noindent + \ttfamily + \hlstd{}\hlkwa{let\ }\hlstd{}\hlkwd{slow\textunderscore echo\ }\hlstd{fd\ }\hlopt{=}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{let\ }\hlstd{}\hlkwd{bytes\ }\hlstd{}\hlopt{=\ }\hlstd{}\hlkwc{Bytes}\hlstd{}\hlopt{.}\hlstd{create\ }\hlnum{1024\ }\hlstd{}\hlkwa{in}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{let\ }\hlstd{}\hlkwd{n\ }\hlstd{}\hlopt{=\ }\hlstd{}\hlkwc{Unix}\hlstd{}\hlopt{.}\hlstd{recv\ fd\ }\hlkwd{bytes\ }\hlstd{}\hlnum{0\ 1024\ }\hlstd{}\hlopt{{[}{]}\ }\hlstd{}\hlkwa{in}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwc{Unix}\hlstd{}\hlopt{.}\hlstd{sleep\ }\hlnum{1}\hlstd{}\hlopt{;}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwc{Unix}\hlstd{}\hlopt{.}\hlstd{send\ fd\ }\hlkwd{bytes\ }\hlstd{}\hlnum{0\ }\hlstd{}\hlkwd{n\ }\hlstd{}\hlopt{{[}{]}}\hlstd{}\hspace*{\fill}\\ + \mbox{} + \end{block} +\end{frame} + +\begin{frame}{Comparing Synchronous \& Asynchronous} + \begin{block}{\underline{Asynchronous Bind}} + \noindent + \ttfamily + \hlstd{}\hlkwa{let\ }\hlstd{}\hlkwd{slow\textunderscore echo\ }\hlstd{fd\ }\hlopt{=}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{let\ }\hlstd{}\hlkwd{bytes\ }\hlstd{}\hlopt{=\ }\hlstd{}\hlkwc{Bytes}\hlstd{}\hlopt{.}\hlstd{create\ }\hlnum{1024\ }\hlstd{}\hlkwa{in}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{bind}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ \ \ }\hlstd{}\hlopt{(}\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{recv\ fd\ }\hlkwd{bytes\ }\hlstd{}\hlnum{0\ 1024\ }\hlstd{}\hlopt{{[}{]})}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ \ \ }\hlstd{}\hlopt{(}\hlstd{}\hlkwa{fun\ }\hlstd{n\ }\hlopt{{-}$>$}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ \ \ \ \ \ }\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{bind}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ \ \ \ \ \ \ \ }\hlstd{}\hlopt{(}\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{sleep\ }\hlnum{1}\hlstd{}\hlopt{)}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ \ \ \ \ \ \ \ }\hlstd{}\hlopt{(}\hlstd{}\hlkwa{fun\ }\hlstd{}\hlopt{()\ {-}$>$}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ \ \ \ \ \ \ \ \ \ \ }\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{send\ fd\ }\hlkwd{bytes\ }\hlstd{}\hlnum{0\ }\hlstd{n\ }\hlopt{{[}{]}))}\hlstd{}\hspace*{\fill}\\ + \mbox{} + \end{block} +\end{frame} + +\begin{frame}{Comparing Synchronous \& Asynchronous} + \begin{block}{\underline{Asynchronous}} + \noindent + \ttfamily + \hlstd{}\hlkwa{let\ }\hlstd{}\hlkwd{slow\textunderscore echo\ }\hlstd{fd\ }\hlopt{=}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{let\ }\hlstd{}\hlkwd{bytes\ }\hlstd{}\hlopt{=\ }\hlstd{}\hlkwc{Bytes}\hlstd{}\hlopt{.}\hlstd{create\ }\hlnum{1024\ }\hlstd{}\hlkwa{in}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{recv\ fd\ }\hlkwd{bytes\ }\hlstd{}\hlnum{0\ 1024}\hlstd{}\hlopt{)\ {[}{]}}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlopt{$>$$>$=\ }\hlstd{}\hlkwa{fun\ }\hlstd{n\ }\hlopt{{-}$>$}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{sleep\ }\hlnum{1}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlopt{$>$$>$=\ }\hlstd{}\hlkwa{fun\ }\hlstd{}\hlopt{()\ {-}$>$}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwc{Async}\hlstd{}\hlopt{.}\hlstd{send\ fd\ }\hlkwd{bytes\ }\hlstd{}\hlnum{0\ }\hlstd{n\ }\hlopt{{[}{]}}\hlstd{}\hspace*{\fill}\\ + \mbox{} + \end{block} +\end{frame} + +\begin{frame}{It's all about the concurrency} + \begin{itemize} + \item The above example is just sequential code. + \item What's actually important is we can do \emph{a lot} of those at the same + time. + \end{itemize} +\end{frame} + +\begin{frame}{Two Components} + \begin{itemize} + \item \textbf{Promises} - Define a graph of things-that-are-not-done and + things-that-want-to-know-when-they-are-done. + \item \textbf{Event loop/Scheduler} - Handle waiting for events and telling + kernel about new events and fulfilling promises. + \end{itemize} +\end{frame} + +\begin{frame}{Promise API} + \noindent + \ttfamily + \hlstd{}\hlkwa{type\ }\hlstd{}\hlopt{+}\hlstd{'a\ t}\hspace*{\fill}\\ + \hlstd{}\hspace*{\fill}\\ + \hlstd{}\hlkwa{val\ }\hlstd{return\ }\hlopt{:\ }\hlstd{'a\ }\hlopt{{-}$>$\ }\hlstd{'a\ t}\hspace*{\fill}\\ + \hlstd{}\hlkwa{val\ }\hlstd{bind\ }\hlopt{:\ }\hlstd{'a\ t\ }\hlopt{{-}$>$\ (}\hlstd{'a\ }\hlopt{{-}$>$\ }\hlstd{'b\ t}\hlopt{)\ {-}$>$\ }\hlstd{'b\ t}\hspace*{\fill}\\ + \hlstd{}\hspace*{\fill}\\ + \hlstd{}\hlkwa{module\ }\hlstd{Infix\textunderscore monad\ }\hlopt{:\ }\hlstd{}\hlkwa{sig}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{val\ }\hlstd{}\hlopt{($>$$>$=)\ :\ }\hlstd{'a\ t\ }\hlopt{{-}$>$\ (}\hlstd{'a\ }\hlopt{{-}$>$\ }\hlstd{'b\ t}\hlopt{)\ {-}$>$\ }\hlstd{'b\ t}\hspace*{\fill}\\ + \hlstd{}\hlkwa{end}\hlstd{}\hspace*{\fill}\\ + \mbox{} +\end{frame} + +\begin{frame}{Promise API} + \hlstd{}\hlkwa{module\ }\hlstd{Promise\ }\hlopt{:\ }\hlstd{}\hlkwa{sig}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{type\ }\hlstd{'a\ fut\ }\hlopt{=\ }\hlstd{'a\ t}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{type\ }\hlstd{'a\ t}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{val\ }\hlstd{create\ }\hlopt{:\ }\hlstd{}\hlkwb{unit\ }\hlstd{}\hlopt{{-}$>$\ }\hlstd{'a\ t}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{val\ }\hlstd{future\ }\hlopt{:\ }\hlstd{'a\ t\ }\hlopt{{-}$>$\ }\hlstd{'a\ fut}\hspace*{\fill}\\ + \hlstd{}\hlstd{\ \ }\hlstd{}\hlkwa{val\ }\hlstd{set\ }\hlopt{:\ }\hlstd{'a\ t\ }\hlopt{{-}$>$\ }\hlstd{'a\ }\hlopt{{-}$>$\ }\hlstd{}\hlkwb{unit\ }\hlstd{fut}\hspace*{\fill}\\ + \hlstd{}\hlkwa{end}\hspace*{\fill}\\ +\end{frame} \end{document} diff --git a/presentation/images/event_loop.png b/presentation/images/event_loop.png new file mode 100644 index 0000000000000000000000000000000000000000..17e47165b552d6c031629c22e4cb604c76a34ae3 GIT binary patch literal 10233 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 KdPS!%-TF5+&7g7s diff --git a/presentation/images/slow_echo_event_loop.png b/presentation/images/slow_echo_event_loop.png new file mode 100644 index 0000000000000000000000000000000000000000..4882f6cda0574b49b974b93c93d01d9f1584219f GIT binary patch literal 11816 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 TT_ptw@ORws6f#Hu+^zouf9rNj diff --git a/presentation/images/slow_echo_sync.png b/presentation/images/slow_echo_sync.png new file mode 100644 index 0000000000000000000000000000000000000000..de84249f95709bd9f023c74979f0b775ffb945a6 GIT binary patch literal 7408 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 al9ma#yQH$rRn$Ph-!Xd^yUN49*ZvQl^MsB7 diff --git a/presentation_code/slow_echo_event_loop.ml b/presentation_code/slow_echo_event_loop.ml new file mode 100644 --- /dev/null +++ b/presentation_code/slow_echo_event_loop.ml @@ -0,0 +1,7 @@ +let slow_echo fd = + let bytes = Bytes.create 1024 in + Async.recv fd bytes 0 1024) [] + >>= fun n -> + Async.sleep 1 + >>= fun () -> + Async.send fd bytes 0 n [] diff --git a/presentation_code/slow_echo_event_loop_bind.ml b/presentation_code/slow_echo_event_loop_bind.ml new file mode 100644 --- /dev/null +++ b/presentation_code/slow_echo_event_loop_bind.ml @@ -0,0 +1,9 @@ +let slow_echo fd = + let bytes = Bytes.create 1024 in + Async.bind + (Async.recv fd bytes 0 1024 []) + (fun n -> + Async.bind + (Async.sleep 1) + (fun () -> + Async.send fd bytes 0 n [])) diff --git a/presentation_code/slow_echo_sync.ml b/presentation_code/slow_echo_sync.ml new file mode 100644 --- /dev/null +++ b/presentation_code/slow_echo_sync.ml @@ -0,0 +1,5 @@ +let slow_echo fd = + let bytes = Bytes.create 1024 in + let n = Unix.recv fd bytes 0 1024 [] in + Unix.sleep 1; + Unix.send fd bytes 0 n []