Skip to content

Commit

Permalink
Changes on slides
Browse files Browse the repository at this point in the history
  • Loading branch information
roman committed Jun 12, 2013
1 parent 1870f24 commit db3b064
Show file tree
Hide file tree
Showing 3 changed files with 172 additions and 83 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# A Shorter Path from Clojure to Clojurescript
# Basics in Haskell Concurrency


Open presentation-output.html file located in the root of the project
Expand All @@ -7,3 +7,5 @@ to see slideshow.

This presentation was developed using Google's [slideshow template from
Google IO 2012](http://code.google.com/p/io-2012-slides/).

Contents were inspired on Simon Marlow's [presentations](http://community.haskell.org/~simonmar/bib/bib.html).
134 changes: 85 additions & 49 deletions presentation-output.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ <h2 data-config-subtitle><!-- populated from slide_config.json --></h2>
<h2>Disclaimer</h2>
<h3></h3>
</hgroup>
<article ><p>This is not a talk about parallelism, is about concurrency.</p>
<article ><p>About concurrency, not parallelism</p>
<p>Parallelism:</p>
<ul>
<li>Program does same thing regardless of the amount of cores</li>
Expand All @@ -65,7 +65,22 @@ <h3></h3>
<li>IO Monad everywhere!</li>
<li>Effects from multiple threads are interleaved (non-deterministic)</li>
<li>Necessary to deal with multiple sources of input/output</li>
</ul></article>
</ul>
<aside class="note">

<ul>
<li>Independently of the # of cores, it will do the same thing</li>

<li>pure</li>

<li>IO Monad everywhere, at least the construct parts</li>

<li>All actions are hapenning at the same time, results may vary in different executions</li>

<li>User Input / Server Background input, etc</li>
</ul>

</aside></article>

</slide>

Expand Down Expand Up @@ -132,19 +147,15 @@ <h3></h3>
</pre>

<ul>
<li>
<p>Creates a new thread to run on the IO action</p>
</li>
<li>
<p>new thread runs "at the same time" as the current thread.</p>
</li>
<li>Creates a new thread to execute the given IO action</li>
<li>new thread runs "at the same time" as the current thread.</li>
</ul>
<aside class="note">

- dalap single traversal with custom tree modification at any level of the tree
- kibit uses backtracking to accomplish this
- You may both, kibit on your dalap transformation functions

<ul>
<li>What can you do with a ThreadId?</li>
<li> Compare threads </li>
<li> Send messages to threads (more on that later)</li>
</ul>
</aside></article>

</slide>
Expand All @@ -162,7 +173,7 @@ <h3></h3>

main = do
hSetBuffering stdout NoBuffering
-- forkIO :: IO () -> IO ThreadId
<b>-- forkIO :: IO () -> IO ThreadId</b>
forkIO $ forever (putChar 'A')
forkIO $ forever (putChar 'B')
threadDelay (10 ^ 6)
Expand All @@ -184,12 +195,18 @@ <h3></h3>

<hgroup>
<h2>A note about performance</h2>
<h3>threading is freaking cheap!</h3>
<h3>Green threads are freaking cheap!</h3>
</hgroup>
<article ><p>1 MILLION threads require around 1.5 GB of storage (approx. 1.5k per thread)</p>
<article ><p>1 MILLION green threads require around 1.5 GB of memory space (approx. 1.5k per thread)</p>
<p><center>
<img src="/images/use_the_forkio.jpeg" class="reflect" alt="Use the forkIO!">
</center></p></article>
</center></p>
<aside class="note">
They are not system threads, this threads are managed by an Internal IO scheduler</br>

Feel free to use as much of them as you need

</aside></article>

</slide>

Expand Down Expand Up @@ -223,7 +240,15 @@ <h3>The most basic concurrency tool in Haskell</h3>
<li>When full and want to put a value, <b>blocks</b></li>
<li>When empty and want to take a value, <b>blocks</b></li>
<li>Doesn't block otherwise</li>
</ul></article>
</ul>
<aside class="note">
<ul>
<li>Like to think of an MVar as a Pint of Beer, Beer => Content; Glass => MVar</li>
<li>Glass can have two states, filled with drink or empty</li>
<li>Can't drink from an empty glass, wait/block until is full</li>
<li>Can't fill up a full glass, wait/block until it is consumed</li>
</ul>
</aside></article>

</slide>

Expand All @@ -243,8 +268,8 @@ <h3>First attempt</h3>
forkIO $ getURL "http://www.wikipedia.org/wiki/haskell" >>= putMVar m1
forkIO $ getURL "http://www.haskell.org/" >>= putMVar m2

r1 <- takeMVar m1
r2 <- takeMVar m2
<b>r1 <- takeMVar m1
r2 <- takeMVar m2</b>

return (r1, r2)
</pre></article>
Expand All @@ -264,11 +289,11 @@ <h3>Abstracting the pattern</h3>
async :: IO a -> IO (Async a)
async action = do
m <- newEmptyMVar
forkIO $ action >>= putMVar m
forkIO $ do { result <- action; putMVar m result; }
return (Async m)

wait :: Async a -> IO a
wait (Async m) = readMVar m
wait (Async m) = <b>readMVar m</b>
-- ^ read != take, doesn't take out the value from
-- the MVar box

Expand Down Expand Up @@ -309,7 +334,7 @@ <h3>Third Attempt</h3>
...
]

downloadPages = mapM (async . http) sites >>= mapM wait
downloadPages = mapM <b>(async . http)</b> sites >>= <b>mapM wait</b>
where
http url = do
(result, time) <- timeit $ getURL url
Expand Down Expand Up @@ -341,15 +366,14 @@ <h3></h3>
<li>
<p><b>one-spot-channel</b></p>
<ul>
<li>Since an MVar holds at most one value, it behaves like an
async channel with buffer-size of one</li>
<li><code>MVars</code> holds at most one value =&gt; async channel of buffer-size one</li>
</ul>
</li>
<li>
<p><b>building block</b></p>
<ul>
<li>MVar can be used to build many different concurrent data
structures/abstractions</li>
<li><code>MVars</code> can be used to build other concurrent data
structures / abstractions (e.g <code>Async</code>)</li>
</ul>
</li>
</ul></article>
Expand All @@ -363,16 +387,10 @@ <h2>A note on fairness in MVars</h2>
<h3></h3>
</hgroup>
<article ><ul>
<li>
<p>Threads blocked on an MVar are processed in a FIFO fashion</p>
</li>
<li>
<p>Each <code>putMVar</code> wakes exactly <b>one</b> thread, and performs
blocked operation atomically</p>
</li>
<li>
<p>Fairness can lead to alternation when two threads compete for an MVar</p>
<ul>
<li>Blocks in FIFO fashion</li>
<li><code>putMVar</code> wakes exactly <b>one</b> thread and is atomic</li>
<li><code>MVar</code> contention may be expensive.</li>
<li>Fairness can lead to alternation when two threads compete for an MVar<ul>
<li>thread A: takeMVar (succeeds)</li>
<li>thread B: takeMVar (blocks)</li>
<li>thread A: putMVar (succeeds, and wakes thread B)</li>
Expand All @@ -381,9 +399,6 @@ <h3></h3>
while MVar is full</li>
</ul>
</li>
<li>
<p>MVar contention may be expensive!</p>
</li>
</ul></article>

</slide>
Expand Down Expand Up @@ -464,7 +479,10 @@ <h3>introducing `throwTo`</h3>
(\file -&gt; ...) -- do
</pre></p>
</li>
</ul></article>
</ul>
<aside class="note">
Remember the ThreadId from forkIO?
</aside></article>

</slide>

Expand All @@ -488,7 +506,7 @@ <h3>Extending Async to handle interruptions</h3>
wait (Async m) = readMVar m

-- we want to add
cancel :: Async a -> IO ()
<b>cancel :: Async a -> IO ()</b>
</pre></article>

</slide>
Expand All @@ -500,7 +518,7 @@ <h2>Example</h2>
<h3>Modify Async definition</h3>
</hgroup>
<article ><pre class="prettyprint lang-hs" data-lang="HASKELL">
newtype Async a = Async <b>ThreadId</b> (MVar a)
data Async a = Async <b>ThreadId</b> (MVar a)

async :: IO a -> IO (Async a)
async io = do
Expand Down Expand Up @@ -529,7 +547,11 @@ <h3>Modify Async definition</h3>
<p>Should it return if the <code>Async</code> was cancelled?</p>
<p>Cancellation is an exception, so wait should return the Exception
that was thrown...</p>
<p><b>Extra WIN</b>: safe handling of other errors as well</p></article>
<p><b>Extra WIN</b>: safe handling of other errors as well</p>
<aside class="note">
Not just that, what about errors? we naively designed
this thinking that IO actions won't have errors on them.
</aside></article>

</slide>

Expand Down Expand Up @@ -653,7 +675,14 @@ <h3>What is it?</h3>
<li>much easier to manage error conditions (async exceptions included)</li>
</ul>
</li>
</ul></article>
</ul>
<aside class="note">
<ul>
<li>Imagine Database Transactions happening in Memory</li>
<li>Same approach, have an execution log, sync at the very end,
were any vars modified while doing this? YAY try again, Nay, good to go</li>
</ul>
</aside></article>

</slide>

Expand All @@ -665,7 +694,11 @@ <h3>A Window Manager</h3>
</hgroup>
<article ><article class="flexbox vcenter">
<img src="images/Desktop.png" width="500px" height="400px" alt="Desktop Pic" title="Desktop Pic">
</article></article>
</article>

<aside class="note">
No crazy UI code here, just logic state, how can we represent this?
</aside></article>

</slide>

Expand All @@ -680,8 +713,8 @@ <h3>Implementation details</h3>
<li>On thread to listen to the user</li>
<li>One thread for each client application</li>
<li>One thread to render the display</li>
<li>All threads share the state of the desktops, at the same time.</li>
</ul>
<p>All threads share the state of the desktops at the same time.</p>
<p>How should we represent this using Haskell's toolbelt?</p></article>

</slide>
Expand Down Expand Up @@ -815,7 +848,6 @@ <h2>STM</h2>
<h3>Basic API</h3>
</hgroup>
<article ><pre class="prettyprint lang-hs" data-lang="HASKELL">

data STM a -- abstract
instance Monad STM -- amongst other things
atomically :: STM a -> IO a
Expand All @@ -825,6 +857,10 @@ <h3>Basic API</h3>
readTVar :: TVar a -> STM a
writeTVar :: TVar a -> a -> STM ()

data TChan a -- abstract
newTChan :: STM (TChan a)
readTChan :: TChan a -> STM a
writeTChan :: TChan a -> a -> STM ()
</pre>

<p>Implementation doesn't use a global lock, two transactions operating on
Expand All @@ -836,7 +872,7 @@ <h3>Basic API</h3>

<hgroup>
<h2>STM</h2>
<h3>Composability</h3>
<h3>Composable Transactions</h3>
</hgroup>
<article ><p>Write an operation to swap to Windows</p>
<pre class="prettyprint lang-hs" data-lang="HASKELL">
Expand Down
Loading

0 comments on commit db3b064

Please sign in to comment.