More Related Content Similar to Ruby 1.9 Fibers (20) Ruby 1.9 Fibers1. Ruby 1.9 Fibers
Cooperative Multi-Processing and Elegant Event-Driven
Programming
Kevin Ball
Co-Founder and CTO
fashioningchange.com
kball@fashioningchange.com
http://twitter.com/kbal11
4. Processes
• Independent (no shared
state)
• Interact via message
passing if at all
• Preemptively scheduled
• Fairly heavyweight
8. Why Processes?
• OS managed
• Task-level parallelism
• Great for embarrassingly parallel (IE web)
14. Why Threading?
• Resource Utilization
• Asynchronous I/O
• Shared Data or Tight Coupling
• Good for fine-grained parallelism
24. How Lightweight?
Threads Fibers
Time to create
1.14 sec 0.103 sec
10,000
Memory for 1000
20.6M 3.3M
Simultaneous
28. Example: Fibonacci
fib = Fiber.new do
f1 = f2 = 1
loop do
Fiber.yield f1
f1, f2 = f2, f1 + f2
end
end
5.times { puts fib.resume }
29. Example: Fibonacci
fib = Fiber.new do
f1 = f2 = 1
loop do
Fiber.yield f1
f1, f2 = f2, f1 + f2
end
end
5.times { puts fib.resume }
1
1
2
3
5
30. Implicit Objects
fib = Fiber.new do
f1 = f2 = 1
loop do
Fiber.yield f1
f1, f2 = f2, f1 + f2
end
end
5.times { puts fib.resume }
31. Implicit Objects
fib = Fiber.new do fib = Object.new
f1 = f2 = 1 fib.instance_eval do
loop do @f1 = @f2 = 1;
Fiber.yield f1 def next
f1, f2 = f2, f1 + f2 @old = @f1
end @f1, @f2 = @f1, @f2, @f1 + @f2
end @old
end
5.times { puts fib.resume } end
5.times { puts fib.next }
34. Why Bother?
Aren’t blocks just implicit functions?
Changing the semantics changes the game.
35. Why Bother?
Aren’t blocks just implicit functions?
Changing the semantics changes the game.
Fibers have more flexible entry points
38. Synchronous
Asynchronicity
Write code that looks like
puts "Setting up HTTP request #1"
data = async_fetch('http://www.google.com/')
puts "Fetched page #1: #{data.response_header.status}"
*Example from http://www.igvita.com/2009/05/13/fibers-cooperative-scheduling-in-ruby/
39. Synchronous
Asynchronicity
Write code that looks like
puts "Setting up HTTP request #1"
data = async_fetch('http://www.google.com/')
puts "Fetched page #1: #{data.response_header.status}"
Looks synchronous. Acts asynchronous.
*Example from http://www.igvita.com/2009/05/13/fibers-cooperative-scheduling-in-ruby/
46. What Is Event-Driven
Programming?
• Age-old Technique
• Familiar to UI & Kernel Developers
• Control Flow determined by Events
47. What Is Event-Driven
Programming?
• Age-old Technique
• Familiar to UI & Kernel Developers
• Control Flow determined by Events
• Callbacks the central construct
48. EventMachine Example
class Echo < EventMachine::Connection
def post_init
send_data 'Hello'
end
def receive_data(data)
p data
end
end
EventMachine.run {
EventMachine.connect '127.0.0.1', 8081, Echo
}
51. The Downside?
Deeply Nested Events
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 }
}
}
*Example from http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/
53. The Solution? Fibers
def 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.yield
end
*Example from http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/
54. The Solution? Fibers
def 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.yield
end
EventMachine.run do
Fiber.new{
page = http_get('http://www.google.com/')
puts "Fetched page: #{page.response_header.status}"
page = http_get('http://www.google.com/search?q=eventmachine')
puts "Fetched page 2: #{page.response_header.status}"
}.resume
end
*Example from http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/
58. Still ugly, but...
• You can wrap it up in a library
• In fact, someone already did
• gem install em-synchrony
59. Em-Synchrony Example
require 'rubygems'
require 'eventmachine'
require 'em-synchrony'
require 'em-synchrony/em-http'
EventMachine.synchrony do
page = EventMachine::HttpRequest.new("http://www.google.com").get
p "Look Ma! No callbacks! Fetched page: #{page}"
EventMachine.stop
end
62. Where is it going?
• Rails 3.1 Automatic Flushing
• Goliath Webserver
63. Where is it going?
• Rails 3.1 Automatic Flushing
• Goliath Webserver
• Async Rails
65. Ruby FTW
• Event-based architectures are
winning
66. Ruby FTW
• Event-based architectures are
winning
• Fibers => Events - Drawbacks
67. Ruby FTW
• Event-based architectures are
winning
• Fibers => Events - Drawbacks
• WIN!
69. Thank You!
Kevin Ball
Co-Founder and CTO
fashioningchange.com
kball@fashioningchange.com
http://twitter.com/kbal11
Editor's Notes \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 \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