Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

93
Paradigms of core.async Clojure Conj Washington Nov 2014 Julian Gamble @juliansgamble

description

This is a talk given at Clojure Conj 2014 in Washington DC. The title was Paradigms of core.async and it was given by Julian Gamble. The code and demos are available here: https://github.com/juliangamble/clojure-conj-2014-paradigms-of-core-async

Transcript of Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Page 1: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Paradigms  of  core.async

Clojure  Conj  Washington    Nov  2014  

Julian  Gamble  @juliansgamble  

Page 2: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Paradigms  of  core.async

Clojure  Conj  Washington    Nov  2014  

Julian  Gamble  @juliansgamble  

Page 3: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Paradigms  of  core.async

Clojure  Conj  Washington    Nov  2014  

Julian  Gamble  @juliansgamble  

Page 4: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Core.async is about:

Page 5: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Core.async is about:

• queues in your application

Page 6: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Core.async is about:

• queues in your application

• making your application simpler to reason about

Page 7: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Benefits

In this talk you will gain an understanding of: • go blocks and how they do concurrency • core.async queues

Page 8: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Benefits

In this talk you will gain an understanding of: • go blocks and how they do concurrency • core.async queues • go block timers • alts! macro and how it enables reading multiple queues

Page 9: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Benefits

In this talk you will gain an understanding of: • go blocks and how they do concurrency • core.async queues • go block timers • alts! functions and how it enables reading multiple queues • how core.async processes work in ClojureScript • the visual impacts of how the core.async function enables

simple ‘process-level’ pauses • how to use core.async to separate out the calculation and

display parts of your code

Page 10: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Benefits

In this talk you will gain an understanding of: • converting a Clojure code-base to ClojureScript • some tips for optimising ClojureScript

Page 11: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

What is core.async?

Page 12: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

What is core.async?

• A set of primitives for creating, reading and writing to queues

• A code walking macro that splices go blocks into state machines

Page 13: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

What is core.async?

• A set of primitives for creating, reading and writing to queues

• A code walking macro that splices go blocks into state machines

• A mechanism for asynchronous computation

• A library in both Clojure and ClojureScript

Page 14: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

What does core.async say about Clojure?

• core.async is implemented using a sophisticated Lisp macro - something only possible in a functional language

• in non-functional languages like Go and C# - CSP is achieved by compiler-extensions - whereas in a functional language like Clojure - this functionality comes as a mere library

Page 15: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

What is CSP?• Communicating Sequential Processes

• Comes out of process calculi – an attempt in the 1960’s and 1970’s to optimise computer usage through specialised algebra.

Page 16: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

What is CSP?• Communicating Sequential Processes

• Comes out of process calculi – an attempt in the 1960’s and 1970’s to optimise computer usage through specialised algebra.

• Based on message passing via channels

• Subject of 1978 Book by C.A.R. Hoare

Page 17: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 18: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

basic example

-­‐main  function

first  go  block

second  go  blockmy-­‐q>! <!

Page 19: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

2-basic-example

Page 20: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

2-basic-example

Page 21: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

2-basic-example

Page 22: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

2-basic-example

Page 23: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

2-basic-example

Page 24: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

basic example

[Demo]

Page 25: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

basic example

Page 26: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

basic multi-channel example-­‐main  function

first  go  block

third  go  block

my-­‐q1>!

alts!

second  go  block my-­‐q2>!

Page 27: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 28: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 29: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 30: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 31: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

basic multi-channel example

[DEMO]

Page 32: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

basic multi-channel example

Page 33: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Tim Baldridge 10K processes

make-­‐scene  function

make-­‐cell  function10K

go  block  1. Set  colour  2. Paint  canvas  cell  3. Pause  for  random  interval  4. Loop

Page 34: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 35: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 36: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 37: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 38: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 39: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

not 10K processes

makeScene  function10K

makeCell  function

mainLoop  function

100

Page 40: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 41: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 42: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 43: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 44: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 45: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

swanodette 10K processes

[go  block]  let  block

[go  block]  render-­‐loop render!‘render’ ‘queue’

[idx  v] [idx  v]

core.async  channel parameter  passed  in  during  function  call

Page 46: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

swanodette 10K processes

No  more  than  1024  pending  puts  are  allowed  on  a  single  channel.

[go  block]  let  block

[go  block]  render-­‐loop render!‘render’ ‘queue’

[idx  v] [idx  v]

core.async  channel parameter  passed  in  during  function  call

Page 47: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 48: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 49: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 50: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 51: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 52: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 53: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 54: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Events with core.async

-­‐main  function

listen  to  DOM  event  and  return  channel

[go  block]  print  queue  message

out/clicksput! <!

Page 55: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

JS event queue

Page 56: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 57: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Parallelism is not Concurrency

Imagine streams of execution in your program

Page 58: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Parallelism is not Concurrency

Imagine streams of execution in your program

Page 59: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Parallelism is not Concurrency

Imagine streams of execution in your program

Page 60: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Parallelism1. For core.async "use it where ever you'd use a queue"

2. In the Tim Baldridge 10K processes example above - it is not explicitly using a queue

(<! (timeout (rand-int 1000)))))))

Page 61: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Parallelism1. For core.async "use it where ever you'd use a queue"

2. In the Tim Baldridge 10K processes example above - it is not explicitly using a queue

(<! (timeout (rand-int 1000)))))))

3. But in the same example - it is implicitly using the queue of the core.async process scheduler - so you're still using a queue.

4. Go blocks are the lightweight equivalent of 'heavyweight' threads

Page 62: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Parallelism1. For core.async "use it where ever you'd use a queue"

2. In the Tim Baldridge 10K processes example above - it is not explicitly using a queue

(<! (timeout (rand-int 1000)))))))

3. But in the same example - it is implicitly using the queue of the core.async process scheduler - so you're still using a queue.

4. Go blocks are the lightweight equivalent of 'heavyweight' threads

5. Heavyweight threads implicitly listen to the queue of the OS 'ready queue'

6. You're already implicitly using queues whenever you use threads.

Page 63: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Quick recap• core.async is all about queues

Page 64: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Quick recap• core.async is all about queues

• queues can used in your application for:

• parallelism

• separating the calculation from the display logic

• event handling

Page 65: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 66: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Rich Hickey original ants demo

Page 67: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Rich Hickey original ants demo-­‐main  function

animation  agent

ant  behaviour  agent

evaporation  agent

world  symbol  (vector  of  vectors)

send-­‐off send-­‐offsend-­‐off

Page 68: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 69: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 70: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 71: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 72: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Converting to ClojureScriptMissing functions in ClojureScript:

Page 73: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Converting to ClojureScriptMissing functions in ClojureScript:

• defstruct - replace with a map

• alter - replace with swap!

Page 74: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Converting to ClojureScriptMissing functions in ClojureScript:

• defstruct - replace with a map

• alter - replace with swap!

• sync

• dosync

• agent

Page 75: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

ants cljs no asyncanimate  function

send-­‐off-­‐animation  function

behave-­‐ants  function

evaporate  function

world  symbol  (vector  of  vectors)

single  call single  callsingle  call

requestAnimationFrame  (callback)

Page 76: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 77: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 78: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 79: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Adding core.async

Page 80: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Adding core.async

• You can use a go block with a timeout queue in the same way you’d use a thread with a sleep function

Page 81: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

adding core.async

Page 82: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

adding core.async

Page 83: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 84: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Using optimisations from David Nolen’s chambered example

• Macros for creating arrays and for-loops

• Underlying assumptions:

• cljs data structures are not yet fully performant - so consider replacing with arrays for speed

• The cljs compiler does not yet fully optimise higher order functions - the most efficient looping construct will be a for-loop macro that uses the loop function

Page 85: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Using optimisations from David Nolen’s chambered example

Page 86: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Using optimisations from David Nolen’s chambered example

Page 87: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

[DEMO]

Page 88: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble
Page 89: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Back to The Italian Job

• Who or what was the hero of the story?

Page 90: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Summary• core.async is about using queues • core.async is about making your application simpler to reason about

Page 91: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Summary• core.async is about using queues • core.async is about making your application simpler to reason about • classic applications are: user interface events, presentation loops,

parallelism in non-parallel environments • you can consider a multithreaded application a queue listener even if

it doesn’t appear to use queues

Page 92: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Summary• core.async is about using queues • core.async is about making your application simpler to reason about • classic applications are: user interface events, presentation loops,

parallelism in non-parallel environments • you can consider a multithreaded application a queue listener even if

it doesn’t appear to use queues • in porting an application from Clojure to ClojureScript you have to

rethink your concurrency • There are lots of optimisations available to make ClojureScript

applications run faster • core.async is not a magic sauce you can sprinkle everywhere - know

when to use it

Page 93: Clojure Conj 2014 - Paradigms of core.async - Julian Gamble

Questions?

Clojure  Conj  Nov  2014  Julian  Gamble  @juliansgamble  

github.com/juliangamble/clojure-­‐conj-­‐2014-­‐paradigms-­‐of-­‐core-­‐async