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.
c1callsheavyonsasynchronously, and blocks on the resultheavyis long running method without IO.c2just 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 c1Complete 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 c1Submit c1 to the pool.
# pseudocode
s = ->
long_running()
print "heavy"
*c1 = ->
s.fork
pool.execute c2
s.join
c2 = ->
print "nonblock"
main = ->
pool.execute c1c1 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 c1Fork 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 c1Submit c2 to the pool.
# pseudocode
s = ->
long_running()
print "heavy"
c1 = ->
s.fork
pool.execute c2
* s.join
c2 = ->
print "nonblock"
main = ->
pool.execute c1c1 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