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
Outline
• Multi-Processing Overview
• Ruby Fibers
• Event Driven Programming
• Fibers + Events => Ruby FTW
Multi-Processing
• Processes
• Threads
• Fibers
• Events
Processes

   • Independent (no shared
     state)
   • Interact via message
     passing if at all
   • Preemptively scheduled
   • Fairly heavyweight
Why Processes?
Why Processes?
• OS managed
Why Processes?
• OS managed
• Task-level parallelism
Why Processes?
• OS managed
• Task-level parallelism
• Great for embarrassingly parallel (IE web)
Threads
• Shared Data
• Fairly lightweight
• Also Preemptively Scheduled
Why Threading?
Why Threading?
• Resource Utilization
Why Threading?
• Resource Utilization
• Asynchronous I/O
Why Threading?
• Resource Utilization
• Asynchronous I/O
• Shared Data or Tight Coupling
Why Threading?
• Resource Utilization
• Asynchronous I/O
• Shared Data or Tight Coupling
• Good for fine-grained parallelism
Threading Problems
Threading Problems
Threading Problems
Threading Problems

         • Race conditions
         • Contention
         • Deadlocks
Fibers
Fibers
• Pauseable/Resumable
  Code Blocks
Fibers
• Pauseable/Resumable
  Code Blocks
• Very lightweight
Fibers
• Pauseable/Resumable
  Code Blocks
• Very lightweight
• Cooperatively scheduled
How Lightweight?
How Lightweight?

                  Threads     Fibers

 Time to create
                  1.14 sec   0.103 sec
    10,000
Memory for 1000
                  20.6M        3.3M
 Simultaneous
Cooperative Scheduling
Cooperative Scheduling
          • Explicit yielding and
            resuming
Cooperative Scheduling
          • Explicit yielding and
            resuming
          • No races or need for
            locks
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 }
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
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 }
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 }
Why Bother?
Why Bother?

Aren’t blocks just implicit functions?
Why Bother?

  Aren’t blocks just implicit functions?


Changing the semantics changes the game.
Why Bother?

  Aren’t blocks just implicit functions?


Changing the semantics changes the game.

  Fibers have more flexible entry points
Synchronous
Asynchronicity
Synchronous
Asynchronicity
Have your asynchronous cake
       and eat it too!
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/
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/
Events: The Hot New Thing
Events: The Hot New Thing
  • Node.js
  • Twisted (python)
  • EventMachine
What Is Event-Driven
  Programming?
What Is Event-Driven
  Programming?
What Is Event-Driven
  Programming?
• Age-old Technique
What Is Event-Driven
  Programming?
• Age-old Technique
• Familiar to UI & Kernel Developers
What Is Event-Driven
  Programming?
• Age-old Technique
• Familiar to UI & Kernel Developers
• Control Flow determined by Events
What Is Event-Driven
  Programming?
• Age-old Technique
• Familiar to UI & Kernel Developers
• Control Flow determined by Events
• Callbacks the central construct
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
}
The Downside?
The Downside?
 Deeply Nested Events
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/
The Solution? Fibers
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/
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/
Still ugly, but...
Still ugly, but...


• You can wrap it up in a library
Still ugly, but...


• You can wrap it up in a library
• In fact, someone already did
Still ugly, but...


• You can wrap it up in a library
• In fact, someone already did
• gem install em-synchrony
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
Where is it going?
Where is it going?

• Rails 3.1 Automatic Flushing
Where is it going?

• Rails 3.1 Automatic Flushing
• Goliath Webserver
Where is it going?

• Rails 3.1 Automatic Flushing
• Goliath Webserver
• Async Rails
Ruby FTW
Ruby FTW

  • Event-based architectures are
    winning
Ruby FTW

  • Event-based architectures are
    winning
  • Fibers => Events - Drawbacks
Ruby FTW

  • Event-based architectures are
    winning
  • Fibers => Events - Drawbacks
  • WIN!
More Resources
• http://ruby-doc.org/core-1.9/classes/
  Fiber.html
• http://www.igvita.com/
• https://github.com/eventmachine/
  eventmachine
Thank You!

     Kevin Ball
 Co-Founder and CTO
fashioningchange.com
 kball@fashioningchange.com
  http://twitter.com/kbal11

More Related Content

PDF
Scaling Ruby with Evented I/O - Ruby underground
KEY
Ruby Concurrency and EventMachine
KEY
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
PPTX
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
PPTX
Ruby C10K: High Performance Networking - RubyKaigi '09
PPTX
No Callbacks, No Threads - RailsConf 2010
PDF
Troubleshooting RabbitMQ and services that use it
PDF
Concurrent Ruby Application Servers
Scaling Ruby with Evented I/O - Ruby underground
Ruby Concurrency and EventMachine
Fast, concurrent ruby web applications with EventMachine and EM::Synchrony
No callbacks, No Threads - Cooperative web servers in Ruby 1.9
Ruby C10K: High Performance Networking - RubyKaigi '09
No Callbacks, No Threads - RailsConf 2010
Troubleshooting RabbitMQ and services that use it
Concurrent Ruby Application Servers

What's hot (20)

PDF
Communication in Python and the C10k problem
PDF
Dissecting the rabbit: RabbitMQ Internal Architecture
PPTX
0-60 with Goliath: High performance web services
PDF
Complex Made Simple: Sleep Better with TorqueBox
KEY
Devignition 2011
PDF
Concurrency in Python
PDF
TorqueBox for Rubyists
PDF
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
PDF
Queue your work
KEY
Cooking a rabbit pie
PPTX
Scaling application with RabbitMQ
PDF
Faster PHP apps using Queues and Workers
PDF
TorqueBox at DC:JBUG - November 2011
ODP
Introduction to Python Celery
PDF
The details of CI/CD environment for Ruby
PDF
Apache Camel in the belly of the Docker whale
PDF
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
PDF
About Node.js
PPTX
A complete guide to Node.js
PDF
Cachopo - Scalable Stateful Services - Madrid Elixir Meetup
Communication in Python and the C10k problem
Dissecting the rabbit: RabbitMQ Internal Architecture
0-60 with Goliath: High performance web services
Complex Made Simple: Sleep Better with TorqueBox
Devignition 2011
Concurrency in Python
TorqueBox for Rubyists
TorqueBox: The beauty of Ruby with the power of JBoss. Presented at Devnexus...
Queue your work
Cooking a rabbit pie
Scaling application with RabbitMQ
Faster PHP apps using Queues and Workers
TorqueBox at DC:JBUG - November 2011
Introduction to Python Celery
The details of CI/CD environment for Ruby
Apache Camel in the belly of the Docker whale
Handling 10k requests per second with Symfony and Varnish - SymfonyCon Berlin...
About Node.js
A complete guide to Node.js
Cachopo - Scalable Stateful Services - Madrid Elixir Meetup

Similar to Ruby 1.9 Fibers (20)

PDF
Ruby's Concurrency Management: Now and Future
PDF
Ruby performance - The low hanging fruit
KEY
Concurrency in ruby
PDF
Fiber in the 10th year
PPTX
Fiber in the 10th year
PDF
Lessons Learnt in 2009
PDF
WTF is Twisted?
PPTX
C# Async/Await Explained
PPT
SXSW 2012 JavaScript MythBusters
KEY
Ruby v cpp_preso
PPTX
50 EJB 3 Best Practices in 50 Minutes - JavaOne 2014
KEY
Concurrent Programming Using the Disruptor
PPTX
JS Event Loop
PDF
Bringing Concurrency to Ruby - RubyConf India 2014
PPTX
Python, async web frameworks, and MongoDB
PPTX
parallel-asynchronous-programming-java.pptx
PDF
Torquebox OSCON Java 2011
PDF
Leveragong splunk for finding needle in the Haystack
PDF
"Leveraging the Event Loop for Blazing-Fast Applications!", Michael Di Prisco
PDF
Multithread Your Application
Ruby's Concurrency Management: Now and Future
Ruby performance - The low hanging fruit
Concurrency in ruby
Fiber in the 10th year
Fiber in the 10th year
Lessons Learnt in 2009
WTF is Twisted?
C# Async/Await Explained
SXSW 2012 JavaScript MythBusters
Ruby v cpp_preso
50 EJB 3 Best Practices in 50 Minutes - JavaOne 2014
Concurrent Programming Using the Disruptor
JS Event Loop
Bringing Concurrency to Ruby - RubyConf India 2014
Python, async web frameworks, and MongoDB
parallel-asynchronous-programming-java.pptx
Torquebox OSCON Java 2011
Leveragong splunk for finding needle in the Haystack
"Leveraging the Event Loop for Blazing-Fast Applications!", Michael Di Prisco
Multithread Your Application

More from Kevin Ball (7)

PDF
Flexible UI Components for a Multi-Framework World
PDF
Modern javascript
PDF
Npm Shrinkwrap
PDF
Understanding the Nesting Structure of the Ember.js View Layer
KEY
Intro to Javascript
KEY
Underscore.js
PDF
Omniauth: Future Proof Your Authentication
Flexible UI Components for a Multi-Framework World
Modern javascript
Npm Shrinkwrap
Understanding the Nesting Structure of the Ember.js View Layer
Intro to Javascript
Underscore.js
Omniauth: Future Proof Your Authentication

Recently uploaded (20)

PDF
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
PDF
ment.tech-Siri Delay Opens AI Startup Opportunity in 2025.pdf
PDF
A hybrid framework for wild animal classification using fine-tuned DenseNet12...
PDF
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
PPTX
Blending method and technology for hydrogen.pptx
PPTX
AQUEEL MUSHTAQUE FAKIH COMPUTER CENTER .
PDF
AI.gov: A Trojan Horse in the Age of Artificial Intelligence
PDF
Human Computer Interaction Miterm Lesson
PPTX
Report in SIP_Distance_Learning_Technology_Impact.pptx
PDF
Transform-Your-Factory-with-AI-Driven-Quality-Engineering.pdf
PDF
Connector Corner: Transform Unstructured Documents with Agentic Automation
PDF
5-Ways-AI-is-Revolutionizing-Telecom-Quality-Engineering.pdf
PDF
NewMind AI Weekly Chronicles – August ’25 Week IV
PPTX
Build automations faster and more reliably with UiPath ScreenPlay
PDF
SaaS reusability assessment using machine learning techniques
PPTX
How to use fields_get method in Odoo 18
PDF
Launch a Bumble-Style App with AI Features in 2025.pdf
PDF
Build Real-Time ML Apps with Python, Feast & NoSQL
PPTX
Presentation - Principles of Instructional Design.pptx
PDF
CCUS-as-the-Missing-Link-to-Net-Zero_AksCurious.pdf
The-2025-Engineering-Revolution-AI-Quality-and-DevOps-Convergence.pdf
ment.tech-Siri Delay Opens AI Startup Opportunity in 2025.pdf
A hybrid framework for wild animal classification using fine-tuned DenseNet12...
Transform-Your-Streaming-Platform-with-AI-Driven-Quality-Engineering.pdf
Blending method and technology for hydrogen.pptx
AQUEEL MUSHTAQUE FAKIH COMPUTER CENTER .
AI.gov: A Trojan Horse in the Age of Artificial Intelligence
Human Computer Interaction Miterm Lesson
Report in SIP_Distance_Learning_Technology_Impact.pptx
Transform-Your-Factory-with-AI-Driven-Quality-Engineering.pdf
Connector Corner: Transform Unstructured Documents with Agentic Automation
5-Ways-AI-is-Revolutionizing-Telecom-Quality-Engineering.pdf
NewMind AI Weekly Chronicles – August ’25 Week IV
Build automations faster and more reliably with UiPath ScreenPlay
SaaS reusability assessment using machine learning techniques
How to use fields_get method in Odoo 18
Launch a Bumble-Style App with AI Features in 2025.pdf
Build Real-Time ML Apps with Python, Feast & NoSQL
Presentation - Principles of Instructional Design.pptx
CCUS-as-the-Missing-Link-to-Net-Zero_AksCurious.pdf

Ruby 1.9 Fibers

  • 1. Ruby 1.9 Fibers Cooperative Multi-Processing and Elegant Event-Driven Programming Kevin Ball Co-Founder and CTO fashioningchange.com [email protected] http://twitter.com/kbal11
  • 2. Outline • Multi-Processing Overview • Ruby Fibers • Event Driven Programming • Fibers + Events => Ruby FTW
  • 4. Processes • Independent (no shared state) • Interact via message passing if at all • Preemptively scheduled • Fairly heavyweight
  • 7. Why Processes? • OS managed • Task-level parallelism
  • 8. Why Processes? • OS managed • Task-level parallelism • Great for embarrassingly parallel (IE web)
  • 9. Threads • Shared Data • Fairly lightweight • Also Preemptively Scheduled
  • 12. Why Threading? • Resource Utilization • Asynchronous I/O
  • 13. Why Threading? • Resource Utilization • Asynchronous I/O • Shared Data or Tight Coupling
  • 14. Why Threading? • Resource Utilization • Asynchronous I/O • Shared Data or Tight Coupling • Good for fine-grained parallelism
  • 18. Threading Problems • Race conditions • Contention • Deadlocks
  • 21. Fibers • Pauseable/Resumable Code Blocks • Very lightweight
  • 22. Fibers • Pauseable/Resumable Code Blocks • Very lightweight • Cooperatively scheduled
  • 24. How Lightweight? Threads Fibers Time to create 1.14 sec 0.103 sec 10,000 Memory for 1000 20.6M 3.3M Simultaneous
  • 26. Cooperative Scheduling • Explicit yielding and resuming
  • 27. Cooperative Scheduling • Explicit yielding and resuming • No races or need for locks
  • 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 }
  • 33. Why Bother? Aren’t blocks just implicit functions?
  • 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/
  • 40. Events: The Hot New Thing
  • 41. Events: The Hot New Thing • Node.js • Twisted (python) • EventMachine
  • 42. What Is Event-Driven Programming?
  • 43. What Is Event-Driven Programming?
  • 44. What Is Event-Driven Programming? • Age-old Technique
  • 45. What Is Event-Driven Programming? • Age-old Technique • Familiar to UI & Kernel Developers
  • 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 }
  • 50. The Downside? Deeply Nested Events
  • 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/
  • 56. Still ugly, but... • You can wrap it up in a library
  • 57. Still ugly, but... • You can wrap it up in a library • In fact, someone already did
  • 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
  • 60. Where is it going?
  • 61. Where is it going? • Rails 3.1 Automatic Flushing
  • 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!
  • 68. More Resources • http://ruby-doc.org/core-1.9/classes/ Fiber.html • http://www.igvita.com/ • https://github.com/eventmachine/ eventmachine
  • 69. Thank You! Kevin Ball Co-Founder and CTO fashioningchange.com [email protected] http://twitter.com/kbal11

Editor's Notes