Fast, concurrent rubyweb applications withEM and EM::Synchrony        Kyle Drake
A bit about me.• Full time Facebook developer• All FB apps: Sinatra + DM, MRI + Thin on EY, Heroku• Lots and lots of slow ...
MapAttack!
MapAttack!• Over 60 hits per second• Lots of network API calls to Geoloqi platform• Lots of scary thread exceptions (Rainb...
What’s going on here?• Blocking IO!• Process spends 90% of time waiting, 10% actually  doing something• Raw performance (T...
Based on the Reactor pattern..        No threads (sortof)       No blocking IO at all      Uses callbacks as events var ap...
CALLBACK HELLvar   useFile = function(filename,callback){      posix.stat(filename).addCallback(function (stats) {        ...
New feature: Joyent Owns It “Any sort of use in commerce, such as promoting a    Platform-as-a-Service or professional ser...
What does Node.js do?It uses the Reactor pattern.       Can we copy it?           YES!
The Reactor Pattern   “The reactor design pattern is a concurrent    programming pattern for handling service   requests d...
• Blocking IO a UNIVERSAL problem• All programming languages have trouble with it• The Reactor pattern resolves it• Most l...
• Blocking IO a UNIVERSAL problem• All programming languages have trouble with it• The Reactor pattern resolves it• Most l...
EventMachine       • Stable, fast, mature, works!       • Production tested       • Thin has EM built in       • Hosting S...
EventMachine                  The Bad• Documentation is weak• It’s weird for synchronous programmers• Education problem - ...
EventMachineWhat if I told you you could do concurrent asynchronous programming, WITHOUT         CALLBACKS?
EM-Synchrony• http://github.com/igrigorik/em-synchrony• “Collection of convenience classes and  primitives to help untangl...
EM-Synchronydef http_get(url)  f = Fiber.current  http = EventMachine::HttpRequest.new(url).get # resume fiber once http c...
EM-SynchronyEventMachine.synchrony do  page = EventMachine::HttpRequest.new("http://www.google.com").get  p "No callbacks!...
EM-Synchrony                         Goliath    http://postrank-labs.github.com/goliathrequire goliathclass Hello < Goliat...
EM-Synchrony                 Goliath• Awesome! But...• Designed for SOA work, not high-level web  development• Doesn’t pla...
Sinatra-Synchrony        http://github.com/kyledrake/sinatra-synchrony•   Tiny glue extension, < 100 LOC•   Same old Sinat...
Conclusions•   You can bake strong concurrency support into Ruby    with almost zero changes to your code•   You can take ...
What You Can Do•   Try this stuff out! Play with it. Teach others how to use    it. Work on the code for it.•   Help me wi...
The Future         Rubinius - Hydra Branch       http://rubini.us/2011/02/17/rubinius-what-s-next• The Smalltalk-80 Blue B...
Thank you.Questions?
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
Upcoming SlideShare
Loading in …5
×

Fast, concurrent ruby web applications with EventMachine and EM::Synchrony

22,631 views

Published on

Fast, concurrent ruby web applications with EventMachine and EM::Synchrony

  1. 1. Fast, concurrent rubyweb applications withEM and EM::Synchrony Kyle Drake
  2. 2. A bit about me.• Full time Facebook developer• All FB apps: Sinatra + DM, MRI + Thin on EY, Heroku• Lots and lots of slow API calls to Facebook• Lots and lots of delayed timeouts, API errors• Lots and lots of users• Lots and lots of performance issues from slow API calls!
  3. 3. MapAttack!
  4. 4. MapAttack!• Over 60 hits per second• Lots of network API calls to Geoloqi platform• Lots of scary thread exceptions (Rainbows! + ThreadSpawn)• Completely unsustainable as a conventional ruby web application
  5. 5. What’s going on here?• Blocking IO!• Process spends 90% of time waiting, 10% actually doing something• Raw performance (Typheous vs Net::HTTP) is almost irrelevant! It’s not your bottleneck.• MRI: No real threads, so IO blocks. 1.8 has green threads, 1.9 has kernel threads with GIL• JRuby: Real kernel threads, much better. But slow (before JIT warms up), special deploy stack, and...
  6. 6. Based on the Reactor pattern.. No threads (sortof) No blocking IO at all Uses callbacks as events var app = express.createServer(); app.get(/, function(req, res){ res.send(Hello World); }); app.listen(3000);Is this the future of web development?
  7. 7. CALLBACK HELLvar useFile = function(filename,callback){    posix.stat(filename).addCallback(function (stats) {        posix.open(filename, process.O_RDONLY, 0666).addCallback(function (fd) {            posix.read(fd, stats.size, 0).addCallback(function(contents){                callback(contents);            });        });    });}; I found far worse examples, but they wouldn’t fit on this page.
  8. 8. New feature: Joyent Owns It “Any sort of use in commerce, such as promoting a Platform-as-a-Service or professional services offering by using the Node.js mark, does require a written license agreement.”“If Joyent notifies you that your use of any trademark is detrimental to any Joyent trademarks or isotherwise unacceptable, you must immediately cease using the marks, blah blah...”
  9. 9. What does Node.js do?It uses the Reactor pattern. Can we copy it? YES!
  10. 10. The Reactor Pattern “The reactor design pattern is a concurrent programming pattern for handling service requests delivered concurrently to a service handler by one or more inputs” - Wikipedia What Node.js does: Takes your blocking IO operation, shoves it into its own kernel threadbehind the scenes, uses Unix kernel magic to make it rejoin the reactor queue when it’s ready. • Linux: epoll(4) • BSD: kqueue/kevent
  11. 11. • Blocking IO a UNIVERSAL problem• All programming languages have trouble with it• The Reactor pattern resolves it• Most languages have the Reactor pattern!
  12. 12. • Blocking IO a UNIVERSAL problem• All programming languages have trouble with it• The Reactor pattern resolves it• Most languages have the Reactor pattern! JavaScript Node.js Python Twisted Ruby EventMachine (libem, C) Java JBoss_Netty (wait, what? I thought Java had good threading..) PHP None yet (perhaps ever)
  13. 13. EventMachine • Stable, fast, mature, works! • Production tested • Thin has EM built in • Hosting Support (CloudFoundry, Heroku)# Source: http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/EventMachine.run { page = EventMachine::HttpRequest.new(http://google.ca/).get page.errback { p "Google is down! terminate?" } page.callback { about = EventMachine::HttpRequest.new(http://google.ca/search?q=eventmachine).get about.callback { # callback nesting, ad infinitum } about.errback { # error-handling code } }}
  14. 14. EventMachine The Bad• Documentation is weak• It’s weird for synchronous programmers• Education problem - nobody understands it• Like Node.js, it requires callback programming• Callbacks don’t play nicely with web frameworks without nasty hacks (async-sinatra, throw :async, et cetera)
  15. 15. EventMachineWhat if I told you you could do concurrent asynchronous programming, WITHOUT CALLBACKS?
  16. 16. EM-Synchrony• http://github.com/igrigorik/em-synchrony• “Collection of convenience classes and primitives to help untangle evented code, plus a number of patched EM clients to make them Fiber aware”• Wraps callbacks in Ruby 1.9 Fibers automatically via EM::Synchrony.sync. The result: NO CALLBACKS!• Anything with a callback method can be patched instantly to support this.
  17. 17. EM-Synchronydef http_get(url) f = Fiber.current http = EventMachine::HttpRequest.new(url).get # resume fiber once http call is done http.callback { f.resume(http) } http.errback { f.resume(http) } return Fiber.yieldendEventMachine.run do Fiber.new{ page = http_get(http://www.google.com/) puts "Fetched page: #{page.response_header.status}" if page page = http_get(http://www.google.com/search?q=eventmachine) puts "Fetched page 2: #{page.response_header.status}" end }.resumeend
  18. 18. EM-SynchronyEventMachine.synchrony do page = EventMachine::HttpRequest.new("http://www.google.com").get p "No callbacks! Fetched page: #{page}" EventMachine.stopend
  19. 19. EM-Synchrony Goliath http://postrank-labs.github.com/goliathrequire goliathclass Hello < Goliath::API # reload code on every request in dev environment use ::Rack::Reloader, 0 if Goliath.dev? def response(env) [200, {}, "Hello World"] endend# > ruby hello.rb -sv# > [97570:INFO] 2011-02-15 00:33:51 :: Starting server on 0.0.0.0:9000
  20. 20. EM-Synchrony Goliath• Awesome! But...• Designed for SOA work, not high-level web development• Doesn’t play nicely with Rack, Thin, Heroku• It’s re-inventing the wheel (I love Sinatra!)• Can we make Sinatra work with EM-Synchrony? YES!
  21. 21. Sinatra-Synchrony http://github.com/kyledrake/sinatra-synchrony• Tiny glue extension, < 100 LOC• Same old Sinatra, concurrency is (mostly) built in.• EventMachine and EM-Synchrony, Rack, Thin, Rainbows!, CloudFoundry, Heroku• Wraps each request in its own Fiber• Only coding change is to use non-blocking drivers/libraries• Patches Rack::Test to make tests run within EM-Synchrony fiber Wow, that was easy.
  22. 22. Conclusions• You can bake strong concurrency support into Ruby with almost zero changes to your code• You can take advantage of this while programming synchronously as usual.. Node.js can’t!• This makes Ruby a real competitor here. Strong performance, concurrency, maintainability, productivity, testing• RUBY IS NOT SLOW. This is a marketing failure, and we need to fix it.
  23. 23. What You Can Do• Try this stuff out! Play with it. Teach others how to use it. Work on the code for it.• Help me with this Sinatra-Synchrony idea. Perhaps we can make the idea more general purpose? Rails support?• DEFEND RUBY FROM THE “RUBY IS SLOW” PEOPLE. Sinatra-Synchrony gets 3000 hits per second in benchmarks on my MacBook with OSX’s crappy network stack, on one core. Productivity and performance are not incompatible here.• It’s my birthday today, get me drunk.
  24. 24. The Future Rubinius - Hydra Branch http://rubini.us/2011/02/17/rubinius-what-s-next• The Smalltalk-80 Blue Book approach is working• They are trashing their GIL with pure ruby!• Supports EventMachine, Fibers coming soon• Because of Evan (and friends), Alan Kay, Ezra, RUBINIUS IS THE FUTURE
  25. 25. Thank you.Questions?

×