Reactor Pattern
✓ UI events: keyboard, mouse, touch
✓ Reusable reactors: browser, game loop
✓ Other events: network up, disk
Monday, October 8, 12
Slide 8
Slide 8 text
Node.js
Node.js uses an event-driven, non-blocking I/O
model that makes it lightweight and efficient, perfect
for data-intensive real-time applications that run across
distributed devices.
Monday, October 8, 12
Slide 9
Slide 9 text
Blocking I/O
If RAM was an F-18 Hornet with a max speed of 1,190 mph, disk
access speed is a banana slug with a top speed of 0.007 mph
Monday, October 8, 12
Slide 10
Slide 10 text
Blocking I/O
data = File.read(‘file.txt’)
F = Fast F18 Hornet
S = Slow Banana Slug
FSSSSSSSSSSSSSSSF
CPU is idle
Monday, October 8, 12
Slide 11
Slide 11 text
Blocking I/O
✓ Switch between busy processes
✓ OS and hardware caches hides complexity
OS
Rails Browser iTunes
Monday, October 8, 12
Slide 12
Slide 12 text
Blocking I/O
OS
Node Browser iTunes
I/O
Node.js switches between I/O within the same process
Monday, October 8, 12
Slide 13
Slide 13 text
Web Apps
✓ blocking I/O decreases concurrency
✓ database, filesystem - disk
✓ S3, external APIs - network
✓ ImageMagick - shelling out
Monday, October 8, 12
Slide 14
Slide 14 text
Rails Concurrency
tweet = Tweet.new(params["tweet"]) # 1.
tweet.shorten_links! # 2. network
tweet.save # 3. disk
Monday, October 8, 12
Slide 15
Slide 15 text
Rails Concurrency
Request
Request
Request
Request
Green is executing thread
Red is waiting on I/O
finished request
start 2nd request
Monday, October 8, 12
Slide 16
Slide 16 text
Rails Concurrency
Web Server
Rails Rails Rails
✓ Process concurrency
✓ Lots of memory
Monday, October 8, 12
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
Monday, October 8, 12
Slide 19
Slide 19 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
Start 1st request
Monday, October 8, 12
Slide 20
Slide 20 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
Monday, October 8, 12
Slide 21
Slide 21 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
Start 2nd request
Monday, October 8, 12
Slide 22
Slide 22 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
Monday, October 8, 12
Slide 23
Slide 23 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
IO finishes for first request
Monday, October 8, 12
Slide 24
Slide 24 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
Monday, October 8, 12
Slide 25
Slide 25 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
IO finishes for last request
Monday, October 8, 12
Slide 26
Slide 26 text
Node Concurrency
Reactor
Request
Request
Reactor
Request
Request
Green is executing thread
Red is waiting on I/O
Monday, October 8, 12
Slide 27
Slide 27 text
Node Concurrency
✓ One reactor process switches between requests
✓ Fewer processes => Less memory
Web Server
Node Node
Monday, October 8, 12
Slide 28
Slide 28 text
Latency
SSSFSSSSSSSSSFSSSS
SSSFSSSSSSSSSFSSSS
SSSFSSSSSSSSSFSSSS
SSSFSSSSSSSSSFSSSS
SSSFSSSSSSSSSFSSSS
JS
Ruby
Single request takes the same time
✓ Blocking I/O is not sped up
✓ Optimize response latency first
Monday, October 8, 12
Procedural Interface,
Evented Execution
response = Faraday.get 'https://github.com/'
✓ hides system event callbacks in libraries
✓ keeps app code clean
Faraday.default_adapter = :em_synchrony
Monday, October 8, 12
Slide 38
Slide 38 text
Procedural Interface,
Evented Execution
Fibers are primitives for implementing light weight
cooperative concurrency in Ruby. Basically
they are a means of creating code blocks that can
be paused and resumed, much like threads. The
main difference is that they are never preempted
and that the scheduling must be done by
the programmer and not the VM.
Monday, October 8, 12
Procedural Interface,
Evented Execution
Reactor
Request
Fiber1
Fiber2
when blocked on I/O, pause Fiber2,
resume Fiber1
Start request
Monday, October 8, 12
Slide 42
Slide 42 text
Procedural Interface,
Evented Execution
Reactor
Request
Fiber1
Fiber2
when blocked on I/O, pause Fiber2,
resume Fiber1
Start request
Resume Fiber in I/O callback
Monday, October 8, 12
Slide 43
Slide 43 text
Code Smell?
...The main difference is that they are never
preempted and that the scheduling must be
done by the programmer and not the VM.
Monday, October 8, 12
Slide 44
Slide 44 text
Just add Fibers
✓ wrap each request in it’s own fiber
✓ web requests are independent from one another
✓ switch between requests instead of processes
Monday, October 8, 12
Slide 45
Slide 45 text
Rack::FiberPool
# Rails
config.middleware.prepend Rack::FiberPool
# Generic rack apps: sinatra, grape, etc
use Rack::FiberPool
Monday, October 8, 12
Slide 46
Slide 46 text
Recap
✓ App server is reactor-aware
✓ One fiber per request
✓ App code is unchanged
Monday, October 8, 12
Slide 47
Slide 47 text
Mixing Paradigms
✓ libraries may block reactor
Request
Request
Request
Request
Reactor
Monday, October 8, 12
Slide 48
Slide 48 text
Mixing Paradigms
✓ libraries may block reactor
Request
Request
Request
Request
Reactor
1st request
Monday, October 8, 12
Slide 49
Slide 49 text
Mixing Paradigms
✓ libraries may block reactor
Request
Request
Request
Request
Reactor
Monday, October 8, 12
Slide 50
Slide 50 text
Mixing Paradigms
✓ libraries may block reactor
Request
Request
Request
Request
Reactor
Blocking library,
doesn’t yield to reactor
Monday, October 8, 12
Slide 51
Slide 51 text
Mixing Paradigms
✓ libraries may block reactor
Request
Request
Request
Request
Reactor
Monday, October 8, 12
Why Node
✓ Single paradigm consistency
✓ Community
Monday, October 8, 12
Slide 63
Slide 63 text
Have cake and eat it too
✓ Don’t go and rewrite your Rails app
✓ Write specific features as an evented subsystem
Monday, October 8, 12
Slide 64
Slide 64 text
Example
https://github.com/blog/678-meet-nodeload-the-new-download-server
Monday, October 8, 12
Slide 65
Slide 65 text
Wrapping Up
Monday, October 8, 12
Slide 66
Slide 66 text
Wrapping Up
✓ Evented programming is hard in any language
Monday, October 8, 12
Slide 67
Slide 67 text
Wrapping Up
✓ Evented programming is hard in any language
✓ Evented programming for evented problems
Monday, October 8, 12
Slide 68
Slide 68 text
Wrapping Up
✓ Evented programming is hard in any language
✓ Evented programming for evented problems
✓ Evented programming doesn’t fix latency
Monday, October 8, 12
Slide 69
Slide 69 text
Wrapping Up
✓ Evented programming is hard in any language
✓ Evented programming for evented problems
✓ Evented programming doesn’t fix latency
✓ Avoid evented I/O interface in app code
Monday, October 8, 12
Slide 70
Slide 70 text
Thanks!
http://github.com/jch
@whatcodecraves
Monday, October 8, 12