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

Modern Concurrency Practices in Ruby

Modern Concurrency Practices in Ruby

Presented at RuLu'14: http://rulu.eu/speakers/#arnab

Avatar for Arnab Deka

Arnab Deka

June 20, 2014

More Decks by Arnab Deka

Other Decks in Technology

Transcript

  1. Agenda I would remove the thread and add actors or

    some other more advanced concurrency features — Matz
  2. Agenda... 4 Elixir 4 Clojure 4 Go 4 Of course,

    Ruby ... 4 Even some French!
  3. Agenda... 4 Elixir 4 Clojure 4 Go 4 Of course,

    Ruby ... 4 Even some French! Sadly, NO Pascal
  4. Arnab 4 @arnab_deka 4 http://arnab-deka.com/ 4 Assam > Kerala >

    Pune > NYC > Seattle > Bangalore 4 Infosys/Goldman > Amazon > LivingSocial 4 C/C++ > Perl > Java > Ruby > Ruby/Clojure
  5. Warm up... counter = Counter.new t1 = Thread.new { 1000.times

    { counter.inc } } t2 = Thread.new { 1000.times { counter.inc } } t1.join; t2.join puts "Final count: #{counter.count}"
  6. STM

  7. STMs: sidetrack on atoms... require 'atomic' class Counter def initialize

    @count = Atomic.new(0) end def inc @count.update { |num| num + 1 } end def count @count.value end end
  8. STMs: sidetrack on atoms... counter = Counter.new t1 = Thread.new

    { 1000.times { counter.inc } } t2 = Thread.new { 1000.times { counter.inc } } t1.join; t2.join puts "Final count, using atomic: #{counter.count}"
  9. STM... (def transfer-count (atom 0)) (let [fn-nonnegative #(>= % 0)]

    (def alice (ref 1000 :validator fn-nonnegative)) (def bob (ref 2000 :validator fn-nonnegative)))
  10. French in the US and in India... 4 ENIEO, not

    ENIAC 4 La sous-traitance, not "outsourcing" 4 ... 4 ... 4 ... 4 "Le Rubis", not Ruby
  11. Actors in Elixir defmodule Player do def play(name) do receive

    do {:serve} -> # do it ... end end end p1 = spawn_link(Player, :play, ["Djokovic"]) send(p1, {:serve}) # or register to a name Process.register(p1, :djoker) send(:djoker, {:serve})
  12. Actors in Ruby class Player include Celluloid def initialize(name); end

    def serve; end end djoker = Player.new djoker.async.serve Player.supervise_as(:djoker, "Djokovic") Celluloid::Actor[:djoker].async.serve
  13. Erlang/Elixir: there's more... 4 Processes are very very light-weight 4

    fault-tolerance: let it crash 4 OTP framework
  14. Erlang/Elixir: there's more... 4 Processes are very very light-weight 4

    fault-tolerance: let it crash 4 OTP framework 4 Distributed
  15. Actors in Ruby: DCell 4 Over 0mq require 'dcell' DCell.start

    :id => "itchy", :addr => "tcp://127.0.0.1:9001" DCell.start :id => "scratchy", :addr => "tcp://127.0.0.1:9002" itchy_node = DCell::Node["itchy"]
  16. Actors 4 focus: named processes/actors 4 coupled to message format

    Channels 4 focus: transport, not receiver 4 anything can produce/consume
  17. core.async: buffering 4 unbuffered by default. Will block on 4

    reading from empty channels 4 writing to non-empty channels
  18. core.async: buffering 4 will buffer upto n: (def bc (chan

    20)) (>!! bc "Hello") (>!! bc "RuLu") (<!! bc) ;;; "Hello" (<!! bc) ;;; "RuLu"
  19. core.async: buffering 4 dropping channels (def c (chan (dropping-buffer 20)))

    4 sliding channels (def c (chan (sliding-buffer 20))) 4 Why not handle buffering automatically?
  20. core.async: go blocks (def c (chan)) (go (let [x (<!

    c) y (<! c)] (println (clojure.string/join " " [x y])))) (>!! c "Hello") (>!! c "RuLu!")
  21. Channels in Ruby require 'jo' include Jo c = chan

    jo do x = c.take y = c.take puts (x + y) end c << 10 c << 25