Your SlideShare is downloading. ×
0
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Ruby Concurrency and EventMachine
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Ruby Concurrency and EventMachine

11,780

Published on

RubyOnBeer presentation with a brief overview of concurrency in ruby and some coverage of EventMachine basics

RubyOnBeer presentation with a brief overview of concurrency in ruby and some coverage of EventMachine basics

Published in: Technology
0 Comments
18 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
11,780
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
77
Comments
0
Likes
18
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Pros: Lots of threads; Cheap to create, execute & cleanup\nCons: Kernel doesn’t know about threads; Blocking\ne.g. new green thread for every http request that comes in... \n
  • Pros: Non blocking; Multi core systems; Shared memory\nCons: Expensive to create; complex context switching; far fewer threads\n
  • Pros: Best of both worlds: Multiple CPUS; Not all threads blocked by system calls; Cheap creation, execution & cleanup\nCons: Green threads blocking on IO can block other Green threads in kernel thread; Hard; Kernel and User scheduler need to work together\n
  • Resource utilization\nAsync IO\n
  • Resource utilization\nAsync IO\n
  • Resource utilization\nAsync IO\n
  • \n
  • Ruby has a legacy of being thread unsafe (e.g. rails only became thread safe 2.2‘ish)\n1.9 Ruby code does not execute on more than one thread concurrently!\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Fast and cheap to setup\n
  • \n
  • \n
  • \n
  • \n
  • Inverted flow control (callback hell)\n... which limit concurrency\n\n
  • Toolkit for creating evented apps\n
  • EM interchangeable with EventMachine\n
  • next_tick -> run code at the next opportunity (always run in main thread)\ndefer -> defer work to run on a thread (green) - 20 by default\nQueue -> data\nChannel -> comms\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    • 1. Ruby Concurrency...and the mysterious case of the Reactor Pattern Christopher Spring
    • 2. or...
    • 3. WTF the EventMachineand why should I care?
    • 4. WTF the EventMachineand why should I care?
    • 5. WTF the EventMachineand why should I care?
    • 6. Resource utilization • Lots of IO (90/10) • Disk • Network • system() • Lots of coreshttp://www.mikeperham.com/2010/01/27/scalable-ruby-processing-with-eventmachine/
    • 7. Ruby concurrency basics • Threads • Fibers • Processes
    • 8. Threading Models 1: N 1 :1 M :N
    • 9. Threading Models 1: NKernel Threads 1 :1 User Threads M :N
    • 10. Threading Models 1: N 1 :1 M :NKernel Threads User Threads
    • 11. Threading Models 1: N • Green Threads • Ruby 1.8 1 :1 • Pros/Cons M :NKernel Threads User Threads
    • 12. Threading Models 1: N 1 :1 M :NKernel Threads User Threads
    • 13. Threading Models 1: N • Native Threads • Ruby 1.9 / jRuby 1 :1 • Pros/Cons M :NKernel Threads User Threads
    • 14. Threading Models 1: N 1 :1 ? M :NKernel Threads User Threads
    • 15. Threads
    • 16. Threads• Shared state and memory space
    • 17. Threads• Shared state and memory space• Relatively light weight
    • 18. Threads• Shared state and memory space• Relatively light weight• Preemptive scheduling
    • 19. Ruby has baggage: GIL http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/
    • 20. Threads... suck
    • 21. Threads... suck• Race conditions
    • 22. Threads... suck• Race conditions• Deadlocks
    • 23. Threads... suck• Race conditions• Deadlocks• Hard to debug
    • 24. Threads... suck• Race conditions• Deadlocks• Hard to debug• GIL
    • 25. Threads... suck• Race conditions• Deadlocks• Hard to debug• GIL
    • 26. Fibers
    • 27. Fibers• It’s a coroutine, dammit!
    • 28. Fibers• It’s a coroutine, dammit! • “... [component to] generalize subroutines to allow multiple entry points for suspending and resuming execution at certain locations.”
    • 29. file_iterator = Fiber.new do file = File.open(stuff.csv, r) while line = file.gets Fiber.yield line end file.closeend3.times{ file_iterator.resume }# => line 1# => line 2# => line 3
    • 30. Fibers• Cooperative Scheduling• Very lightweight• Maintains state• Great for: cooperative tasks, iterators, infinite lists and pipes
    • 31. def interpret_csv( csv_source ) Fiber.new do while csv_source.alive? str = csv_source.resume Fiber.yield str.split(,).map(&:strip) end endenddef file_iterator(file_name) Fiber.new do file = File.open(file_name, r) while line = file.gets Fiber.yield line end file.close endendinterpret_csv( file_iterator(stuff.csv) ).resume# => [...]
    • 32. Reactor Pattern
    • 33. Client Client Client Client IO StreamEvent Handler A Event DispatcherEvent Handler B DemultiplexerEvent Handler CEvent Handler D
    • 34. Benefits• Non blocking IO• Coarse grain concurrency• No threads!• Single Process
    • 35. Limitations• Hard to debug• Dispatch to event handlers is synchronous• Demultiplexer polling limits
    • 36. EventMachine
    • 37. require eventmachineclass EchoServer < EM::Connection def post_init puts "New connecting" end def unbind puts "Connection closed" end def receive_data(data) # unbuffered!! puts "<< #{data}" send_data ">> #{data}" endendEM.run do EM.start_server(127.0.0.1, 9000, EchoServer) puts "Started server at 127.0.0.1:9000"end # Runs till EM.stop called
    • 38. # $ telnet localhost 9000require eventmachine # Hello # >> Helloclass EchoServer < EM::Connection # Bye def post_init # >> Bye puts "New connecting" end def unbind puts "Connection closed" end def receive_data(data) # unbuffered!! puts "<< #{data}" send_data ">> #{data}" endendEM.run do EM.start_server(127.0.0.1, 9000, EchoServer) puts "Started server at 127.0.0.1:9000"end # Runs till EM.stop called
    • 39. Primitives• run loop• next_tick; add_timer; add_periodic_timer• EM.defer• EM::Queue• EM::Channel
    • 40. EM.run do Defer operation = Proc.new do puts MapMap!! sleep 3 puts Done collecting data [1, 1, 2, 3, 5, 8, 13] end callback = Proc.new do |arr| puts Reducing... sleep 1 puts Reduced puts arr.inject(:+) EM.stop end EM.defer(operation, callback)end
    • 41. EM.run do Defer # # # MapMap!! Done collecting data Reducing... # Reduced operation = Proc.new do # 33 puts MapMap!! sleep 3 puts Done collecting data [1, 1, 2, 3, 5, 8, 13] end callback = Proc.new do |arr| puts Reducing... sleep 1 puts Reduced puts arr.inject(:+) EM.stop end EM.defer(operation, callback)end
    • 42. EM.run do Queue queue = EM::Queue.new EM.defer do sleep 2; queue.push Mail 1 sleep 3; queue.push Mail 2 sleep 4; queue.push Mail 3 end mail_sender = Proc.new do |mail| puts "Sending #{mail}" EM.next_tick{ queue.pop(&mail_sender)} end queue.pop(&mail_sender)end
    • 43. ChannelEM.run do channel = EM::Channel.new EM.defer do channel.subscribe do |msg| puts "Received #{msg}" end end EM.add_periodic_timer(1) do channel << Time.now endend
    • 44. class Mailer include EM::Deferrable Deferrable def initialize callback do sleep 1 puts Updated statistics! end errback{ puts retrying mail} end def send rand >= 0.5 ? succeed : fail endendEM.run do 5.times do mailer = Mailer.new EM.add_timer(rand * 5){ mailer.send} endend
    • 45. class Mailer include EM::Deferrable Deferrable def initialize # Updating statistics! callback do # Updating statistics! sleep 1 # retrying mail puts Updated statistics! end errback{ puts retrying mail} end def send rand >= 0.5 ? succeed : fail endendEM.run do 5.times do mailer = Mailer.new EM.add_timer(rand * 5){ mailer.send} endend
    • 46. class Mailer Stacked callbacks include EM::Deferrable EM.run do def add_mailing(val) m = Mailer.new callback{ m.add_mailing(1) sleep 1; m.add_mailing(2) puts "Sent #{val}" m.connection_open! } end EM.add_timer(1) do m.connection_lost! def connection_open! EM.add_timer(2) do puts Open connection m.add_mailing(3) succeed m.add_mailing(4) end m.connection_open! end def connection_lost! end puts Lost connection end set_deferred_status nil endend
    • 47. class Mailer Stacked callbacks include EM::Deferrable EM.run do def add_mailing(val) m = Mailer.new callback{ # Open connection m.add_mailing(1) sleep 1; m.add_mailing(2) # Sent 1 puts "Sent #{val}" m.connection_open! # Sent 2 } end # Lost connection EM.add_timer(1) do # Open connection m.connection_lost! def connection_open! # Sent 3 EM.add_timer(2) do puts Open connection m.add_mailing(3) # Sent 4 succeed m.add_mailing(4) end m.connection_open! end def connection_lost! end puts Lost connection end set_deferred_status nil endend
    • 48. Gotchas• Synchronous code will slow it down • Use/Write libraries for EM• Everything in the event loop must be async!
    • 49. Summary• It’s a blocking world!• Alternative concurrency implementations• Start playing with EM
    • 50. Worth checking out• EM-Synchrony: https://github.com/igrigorik/em-synchrony• Goliath: https://github.com/postrank-labs/goliath
    • 51. Baie Dankie!
    • 52. Questions?
    • 53. Links• http://www.mikeperham.com• http://www.igvita.com (!!)• http://rubyeventmachine.com/

    ×