class: center, middle
Albert Mingkun Yang
- Block: Easy to read, but waste CPU cycles
- Continuation: Utilize CPU fully, but introduce callback hell
// Pyramid of Doom
(function($) {
$(function(){
$("button").click(function(e) {
$.get("/test.json", function(data, textStatus, jqXHR) {
$(".list").each(function() {
$(this).click(function(e) {
setTimeout(function() {
alert("Hello World!");
}, 1000);
});
});
});
});
});
})(jQuery);
Simulating one server (s) interacting with two clients (c1, c2):
- Starts with single thread, and explore what changes using two threads.
c1
callsheavy
ons
asynchronously, and blocks on the resultheavy
is long running method without IO.c2
just prints some string to STDOUT
# pseudocode
class Server
heavy = ->
long_running()
print "heavy"
class Client
block = ->
get s.heavy()
nonblock = ->
print "nonblock"
s = new Server
c1 = new Client
c2 = new Client
c1.block()
c2.nonblock()
Complete code in: bit.ly/sfm15_encore
# pseudocode
s = ->
long_running()
print "heavy"
c1 = ->
s.fork
pool.execute c2
s.join
c2 = ->
print "nonblock"
main = ->
pool.execute c1
Complete code in: bit.ly/sfm15_fork
# pseudocode
s = ->
long_running()
print "heavy"
c1 = ->
s.fork
pool.execute c2
s.join
c2 = ->
print "nonblock"
main = ->
* pool.execute c1
Submit c1 to the pool.
# pseudocode
s = ->
long_running()
print "heavy"
*c1 = ->
s.fork
pool.execute c2
s.join
c2 = ->
print "nonblock"
main = ->
pool.execute c1
c1
is run by the pool
.
# pseudocode
s = ->
long_running()
print "heavy"
c1 = ->
* s.fork
pool.execute c2
s.join
c2 = ->
print "nonblock"
main = ->
pool.execute c1
Fork s
so that s
and c1
could run in parallel potentially.
# pseudocode
s = ->
long_running()
print "heavy"
c1 = ->
s.fork
* pool.execute c2
s.join
c2 = ->
print "nonblock"
main = ->
pool.execute c1
Submit c2
to the pool.
# pseudocode
s = ->
long_running()
print "heavy"
c1 = ->
s.fork
pool.execute c2
* s.join
c2 = ->
print "nonblock"
main = ->
pool.execute c1
c1
waits until s
is finished.
| encore | java
--------------- | ------------------ | ------------------
single thread | heavy; nonblock | heavy; nonblock
two threads | nonblock; heavy | heavy; nonblock
- blocking on futures doesn't block the underlying thread, like green thread
- not optimal if the long running async computation is not long enough
- auto-switching makes more sense for actors, for actors are concurrent
- possibly optimization: busy waiting first, then switching if still not done