Concurrency in ruby
Upcoming SlideShare
Loading in...5
×
 

Concurrency in ruby

on

  • 2,628 views

 

Statistics

Views

Total Views
2,628
Views on SlideShare
2,123
Embed Views
505

Actions

Likes
5
Downloads
10
Comments
0

10 Embeds 505

http://broadcast.marcoborromeo.com 342
http://marcoborromeo.com 131
http://lanyrd.com 21
http://www.typepad.com 3
http://127.0.0.1 2
https://twitter.com 2
https://twimg0-a.akamaihd.net 1
https://si0.twimg.com 1
http://webcache.googleusercontent.com 1
http://mbblog.heroku.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n

Concurrency in ruby Concurrency in ruby Presentation Transcript

  • Concurrency in RubyMarco Borromeo - @borrosItalian Ruby Day - Milan - 15 June 2012
  • Concurrency - Why?Fill up all those cores!
  • Concurrency - Why?Fill up all those cores!Ruby is slow - Just add some more mongrels there
  • Concurrency - Why?Fill up all those cores!Ruby is slow - Just add some more mongrels there
  • How to achieve concurrencyMultiple processes / forkingThreadsFibers
  • Multiple processes / forking Most commonly used solution to gain concurrency in Ruby
  • Multiple processes / forking Most commonly used solution to gain concurrency in Ruby No shared states between running processes. You need to use DRb, a message bus like RabbitMQ
  • Multiple processes / forking Most commonly used solution to gain concurrency in Ruby No shared states between running processes. You need to use DRb, a message bus like RabbitMQ ... or some shared data store like MySQL
  • Multiple processes / forking Most commonly used solution to gain concurrency in Ruby No shared states between running processes. You need to use DRb, a message bus like RabbitMQ ... or some shared data store like MySQL
  • Multiple processes / forking Most commonly used solution to gain concurrency in Ruby No shared states between running processes. You need to use DRb, a message bus like RabbitMQ ... or some shared data store like MySQL Forked processses can read the state of the program before the fork, but updates wont be shared
  • Multiple processes / forking LOT of memory used! 5 Rails apps is something like 45MB * 5 = 255MB! Unix copy-on-write (CoW) comes to help: no need to copy the whole memory into the forked process, and only the data changed after the fork will be copied and modified. but...
  • Multiple processes / forkingRuby Garbage Collector (GC) will write to every object every timeit will run, so the whole process memory will be then copied.Basically, Ruby loses all the benefits of CoW.
  • Multiple processes / forking Passenger fixed the copy-on-write issues creating a CoW- friendly GC, and it will be integrated into Ruby 2.0
  • Multiple processes / forking Passenger fixed the copy-on-write issues creating a CoW- friendly GC, and it will be integrated into Ruby 2.0 Rubinius is CoW friendly
  • How to achieve concurrencyMultiple processes / forkingThreadsFibers
  • ThreadsRuby 1.8 has "green threads". They are scheduled by the VM,and emulate multithreaded environments even if they are not.Ruby 1.9 has OS threads.Preemptive scheduling
  • ThreadsBoth 1.8 and 1.9 have the Global Interpreter Lock (GIL).Having GIL means that any time one thread is running Rubycode, no other thread can be running Ruby code.Even if you have multiple threads, you can only use at most 1core of your CPU at a time.
  • ThreadsRace conditions, dead locks, synchronizing...
  • ThreadsRace conditions, dead locks, synchronizing...
  • ThreadsRace conditions, dead locks, synchronizing...... JRuby manages threads very well, has no GIL and let youuse all your cores.
  • ThreadsRace conditions, dead locks, synchronizing...... JRuby manages threads very well, has no GIL and let youuse all your cores.Rubinius is working on removing GIL
  • How to achieve concurrencyMultiple processes / forkingThreadsFibers
  • Fibers Natively available only in Ruby 1.9 They are like simplified threads, but they arent scheduled by the VM but by the programmer Faster than threads, and use less memory
  • Fibers
  • FibersThey still suffer the GIL presence.
  • Recap
  • RecapForking
  • RecapForking GC prevents us to have a proper memory management
  • RecapForking GC prevents us to have a proper memory managementThreads
  • RecapForking GC prevents us to have a proper memory managementThreads Difficult to manage Difficult to debug in production GIL prevents us to have concurrency
  • RecapForking GC prevents us to have a proper memory managementThreads Difficult to manage Difficult to debug in production GIL prevents us to have concurrencyFibers
  • RecapForking GC prevents us to have a proper memory managementThreads Difficult to manage Difficult to debug in production GIL prevents us to have concurrencyFibers Difficult to debug in production GIL prevents us to have concurrency
  • No Concurrency, sorry.
  • No Concurrency, sorry.
  • Blocking I/O 90% I/O 10% Code Execution
  • Reactor PatternApplication server (AS) receives a request from a browserAS queues the request in the ReactorReactor process the request, passing the control to our AppIn order to process the request, our app needs to perform some APIqueries over third-party services
  • Reactor PatternApplication server (AS) receives a request from a browserAS queues the request in the ReactorReactor process the request, passing the control to our AppIn order to process the request, our app needs to perform some APIqueries over third-party services ...zZzZzzZzZzZ...
  • Reactor PatternApplication server (AS) receives a request from a browserAS queues the request in the ReactorReactor process the request, passing the control to our AppIn order to process the request, our app needs to perform some APIqueries over third-party services ...zZzZzzZzZzZ...
  • Reactor PatternOur app makes the http request to the third-party service, using an asynclibrary (em-http) and provides a callback to be executed when a reply isreceivedControl returns to the ReactorReactor pulls the next event from the queue and executes it
  • Reactor PatternEarlier HTTP API call returns (or fails!) and the callback is enqueued into theReactorControl returns to the ReactorReactor starts executing the callback which processes the results of the APIrequest, builds a response and sends it to the browser.Done
  • Blocking I/O Everything has the advantage of being concurrent without having to be thread-safe. It is a "cooperative multitasking" (while Threads have a “Preemptive scheduling“ approach)
  • EventMachineIs the Ruby implementation of the Reactor Pattern ::DeferrableChildProcess - Wait for a process to exit ::FileStreamer - Streams a file over a connection ::FileWatch - Monitors a file, get notified when it gets deleted, modified or moved ::PeriodicTimer - Executes something every interval seconds
  • EventMachineIs the Ruby implementation of the Reactor Pattern ::Protocols::HttpClient ::Protocols::SmtpServer ::Protocols::Memcache ::Protocols::Socks4 ::Protocols::Postgres3 ::Protocols::Stomp ::Protocols::SmtpClient
  • EventMachineIssues: Not so very well documented Difficult to adopt for "syncronous programmers" Doesnt play well with actual web frameworks
  • EventMachine
  • EventMachineEventMachine.run { page = EventMachine::HttpRequest.new(http://github.com/).get page.errback { p "GitHub is Down. Everybody run for your life!" } page.callback { about = EventMachine::HttpRequest.new(http://github.com/api/v2/json/repos/show/schacon).get about.callback { } about.errback { } }}
  • EM-Syncrony"Collection of convenience classes and primitives to help untangle evented code, plus a number of patched EM clients to make them Fiber aware." EventMachine.synchrony do homepage = EventMachine::HttpRequest.new("http://github.com/").get apiResponse = EventMachine::HttpRequest.new("http://github.com/api/v2/ json/repos/show/schacon").get p "No callbacks! Fetched API: #{apiResponse}" EventMachine.stop end
  • EM-Syncrony mysql2 activerecord Other clients: em-http-request em-redis em-memcached hiredis em-mongo mongoid AMQP
  • Sinatra::Synchrony EventMachine + EM-Syncrony Rack::FiberPool em-http-request em-resolv-replace Patches TCPSocket (via EM-Syncrony) (!) Patches Rack::Test
  • Sinatra::Synchrony gem install sinatra-synchrony require sinatra/synchrony register Sinatra::Synchrony
  • Thanks!Marco Borromeo@borrosmarco@continuityapp.com