Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Evented Ruby vs. Node.js

Jerry Cheung
October 09, 2012

Evented Ruby vs. Node.js

What is evented programming? Why is it useful for server-side web? What are the tradeoffs between using eventmachine and node.js? How can you use evented programming in your Ruby project?

Jerry Cheung

October 09, 2012
Tweet

More Decks by Jerry Cheung

Other Decks in Programming

Transcript

  1. Performance Goals ✓ Low hanging fruit ✓ Micro-optimizations (don’t do

    ‘em) ✓ Sustainable changes ✓ Minimal Monday, October 8, 12
  2. Evented... ✓ ... programming ✓ ... server side web ✓

    ... Ruby vs Javascript ✓ ... app concurrency Monday, October 8, 12
  3. Reactor Pattern ✓ UI events: keyboard, mouse, touch ✓ Reusable

    reactors: browser, game loop ✓ Other events: network up, disk Monday, October 8, 12
  4. 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
  5. 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
  6. Blocking I/O data = File.read(‘file.txt’) F = Fast F18 Hornet

    S = Slow Banana Slug FSSSSSSSSSSSSSSSF CPU is idle Monday, October 8, 12
  7. Blocking I/O ✓ Switch between busy processes ✓ OS and

    hardware caches hides complexity OS Rails Browser iTunes Monday, October 8, 12
  8. Blocking I/O OS Node Browser iTunes I/O Node.js switches between

    I/O within the same process Monday, October 8, 12
  9. Web Apps ✓ blocking I/O decreases concurrency ✓ database, filesystem

    - disk ✓ S3, external APIs - network ✓ ImageMagick - shelling out Monday, October 8, 12
  10. 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
  11. Node Concurrency tweet = new Tweet(); // 1. tweet.shortenLinks(function(tweet) {

    // 2. callback tweet.save(function(tweet) { // 3. callback } }) Monday, October 8, 12
  12. Node Concurrency Reactor Request Request Reactor Request Request Green is

    executing thread Red is waiting on I/O Monday, October 8, 12
  13. 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
  14. Node Concurrency Reactor Request Request Reactor Request Request Green is

    executing thread Red is waiting on I/O Monday, October 8, 12
  15. 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
  16. Node Concurrency Reactor Request Request Reactor Request Request Green is

    executing thread Red is waiting on I/O Monday, October 8, 12
  17. 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
  18. Node Concurrency Reactor Request Request Reactor Request Request Green is

    executing thread Red is waiting on I/O Monday, October 8, 12
  19. 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
  20. Node Concurrency Reactor Request Request Reactor Request Request Green is

    executing thread Red is waiting on I/O Monday, October 8, 12
  21. Node Concurrency ✓ One reactor process switches between requests ✓

    Fewer processes => Less memory Web Server Node Node Monday, October 8, 12
  22. 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
  23. Code Smell ✓ App code aware of blocking I/O ✓

    Ugly syntax, nested contexts tweet = new Tweet(); // 1. tweet.shortenLinks(function(tweet) { // 2. callback tweet.save(function(tweet) { // 3. callback } }) Monday, October 8, 12
  24. Evented Ruby ✓ ruby is capable of evented programming ✓

    multi-paradigm: procedural, evented, parallel ✓ mix and match paradigms Monday, October 8, 12
  25. Ruby Reactors ✓ reactor is just a gem ✓ eventmachine,

    cool.io, ... # Starting an EventMachine reactor EM.run { # reactor aware code here... } Monday, October 8, 12
  26. Code Smell http = EM::HttpRequest.new('https://github.com/').get http.callback { # request finished

    } ✓ app code aware of blocking I/O ✓ code doesn’t look like ruby Monday, October 8, 12
  27. 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
  28. 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
  29. Procedural Interface, Evented Execution Reactor Request Fiber1 Fiber2 when blocked

    on I/O, pause Fiber2, resume Fiber1 Start request Monday, October 8, 12
  30. 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
  31. 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
  32. 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
  33. Recap ✓ App server is reactor-aware ✓ One fiber per

    request ✓ App code is unchanged Monday, October 8, 12
  34. Mixing Paradigms ✓ libraries may block reactor Request Request Request

    Request Reactor 1st request Monday, October 8, 12
  35. Mixing Paradigms ✓ libraries may block reactor Request Request Request

    Request Reactor Blocking library, doesn’t yield to reactor Monday, October 8, 12
  36. Mixing Paradigms ✓ libraries may block reactor Request Request Request

    Request Reactor 2nd request, reactor blocked, can’t start Monday, October 8, 12
  37. Mixing Paradigms ✓ libraries may block reactor Request Request Request

    Request Reactor Reactor starts 2nd request Monday, October 8, 12
  38. But that’s ok... Web Server Rails Rails Rails Can’t do

    worse than one request per process Monday, October 8, 12
  39. System Calls ✓ EM.popen - non-blocking version ✓ EM.defer -

    run blocking call outside of reactor thread Monday, October 8, 12
  40. Final Result Reactor Request Request Fiber1 Fiber2 Fiber3 Green is

    executing thread Red is waiting on I/O Monday, October 8, 12
  41. Why Ruby ✓ Reuse existing code ✓ Performance won’t be

    worse ✓ Keep procedural syntax ✓ Multi-paradigm Monday, October 8, 12
  42. 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
  43. Wrapping Up ✓ Evented programming is hard in any language

    ✓ Evented programming for evented problems Monday, October 8, 12
  44. Wrapping Up ✓ Evented programming is hard in any language

    ✓ Evented programming for evented problems ✓ Evented programming doesn’t fix latency Monday, October 8, 12
  45. 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