Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Live Long and Prosper with Celluloid & JRuby

Live Long and Prosper with Celluloid & JRuby

In this talk you'll learn about the Celluloid ecosystem. We'll take a glance at:

Celluloid - the OOP & Actor model based concurrency framework
Celluloid::IO - an evented I/O framework
DCell - distributed Actors for Celluloid
Reel - the Celluloid::IO powered web server

I'll cover the Actor model - Celluloid's inspiration for their approach to concurrent objects. How we can best achieve concurrency without mind-bending synchronisation, mutexes, deadlocks and all the bad stuff, in idiomatic and simple to grasp Ruby.

We'll finish up by briefly covering JRuby and why it's my preferred Ruby VM for concurrency and true parallelism with Celluloid.

This talk was given at JRubyconf EU - 2013.

Ben Lovell

August 15, 2013
Tweet

More Decks by Ben Lovell

Other Decks in Programming

Transcript

  1. A concurrent object oriented programming framework for Ruby which lets

    you build multithreaded programs out of concurrent objects just as easily as you build sequential programs out of regular objects “
  2.   ACTORS MAY CREATE OTHER ACTORS BUFFER MESSAGES IN

    A MAILBOX PROCESS MESSAGES SERIALLY
  3.  1 class Actor 2 attr_reader :counter 3 4 def

    initialize 5 @counter = 0 6 @mutex = Mutex.new 7 end 8 9 def increment 10 @mutex.synchronize do 11 @counter += 1 12 end 13 end 14 end
  4.  1 require "celluloid" 2 3 class Actor 4 include

    Celluloid 5 attr_reader :counter 6 7 def initialize 8 @counter = 0 9 end 10 11 def increment 12 @counter += 1 13 end 14 end
  5.  1 require "celluloid" 2 3 class Actor 4 include

    Celluloid 5 end 6 7 actor = Actor.new 8 actor.inspect 9 #=> <Celluloid::ActorProxy(Actor:0x3feaecbb38e0)> 10 11 Thread.main 12 #=> <Thread:0x007f86290b8ce8 run> 13 14 actor.thread 15 #=> <Thread:0x007f862ad27a78 sleep>
  6.  1 require "celluloid" 2 3 class Actor 4 include

    Celluloid 5 6 def compute_all_the_things 7 sleep 2 8 puts "42" 9 end 10 end 11 12 actor = Actor.new 13 actor.compute_all_the_things 14 puts "done!" #=> 42 #=> done! blocking
  7.  1 require "celluloid" 2 3 class Actor 4 include

    Celluloid 5 6 def compute_all_the_things 7 sleep 2 8 puts "42" 9 end 10 end 11 12 actor = Actor.new 13 actor.async.compute_all_the_things 14 puts "done!" 15 16 #=> done! 17 #=> 42 non-blocking
  8.  1 require "celluloid" 2 3 class Actor 4 include

    Celluloid 5 6 def compute_all_the_things 7 sleep 2 8 "42" 9 end 10 end 11 12 actor = Actor.new 13 future = actor.future.compute_all_the_things 14 puts "done!" 15 puts future.value 16 17 #=> done! 18 #=> 42 returns immediately blocks until a value is yielded
  9.  1 require "celluloid/autostart" 2 3 class Actor 4 include

    Celluloid 5 6 def compute_all_the_things 7 puts "42" 8 end 9 10 def zomg_crash 11 raise "derp!" 12 end 13 end 14 15 supervisor = Actor.supervise_as :foo 16 17 begin 18 Celluloid::Actor[:foo].zomg_crash 19 rescue 20 puts "whoops" 21 end 22 23 Celluloid::Actor[:foo].compute_all_the_things 24 25 #=> whoops 26 #=> 42 crash the actor fresh actor supervise the actor
  10.  1 require "celluloid" 2 3 class Actor 4 include

    Celluloid 5 6 def compute_all_the_things 7 sleep 1 8 puts "42" 9 end 10 end 11 12 pool = Actor.pool 13 14 4.times { pool.compute_all_the_things } 15 16 #=> 42 17 #=> 42 and so on... size == cores load up the workers
  11.  CELLULOID OO AND CONCURRENCY SYNC, ASYNC AND FUTURES NO

    DEADLOCKS FAULT TOLERANT SIMPLE TO REASON ABOUT
  12. An event-driven IO system for building fast, scalable network applications

    that integrate directly with celluloid actors “
  13. A distributed extension to celluloid which provides distributed and concurrent

    objects for ruby that are both robust and fault-tolerant “
  14.  1 require 'dcell' 2 3 DCell.start :id => "itchy",

    :addr => "tcp://127.0.0.1:9001" 4 5 class Itchy 6 include Celluloid 7 #... 8 end 9 10 Itchy.supervise_as :itchy start a node make your actor available
  15.  1 require 'dcell' 2 3 DCell.start :id => "scratchy",

    :addr => "tcp://127.0.0.1:9002" 4 itchy_node = DCell::Node["itchy"] 5 itchy_node[:itchy].fight! start a node discover itchy node itchy cell
  16. A fast non-blocking and evented web server. Thanks to celluloid,

    Reel works great for multithreaded applications and provides traditional multithreaded blocking IO support too. “
  17.  1 require 'reel' 2 3 class MyServer < Reel::Server

    4 def initialize(host = "127.0.0.1", port = 3000) 5 super(host, port, &method(:on_connection)) 6 end 7 8 def on_connection(connection) 9 while request = connection.request 10 if request.websocket? 11 handle_websocket(request) 12 break 13 else 14 handle_request(request) 15 end 16 end 17 end 18 19 def handle_request(request) 20 request.respond :ok, "Hello, world!" 21 end 22 23 def handle_websocket(sock) 24 sock << "Hello everyone out there in WebSocket land!" 25 sock.close 26 end 27 end 28 29 MyServer.run
  18. ?