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

Concurrency & Ruby

Concurrency & Ruby

Slides for my talk at RubyConf India 2013

Rocky Jaiswal

June 23, 2013
Tweet

More Decks by Rocky Jaiswal

Other Decks in Programming

Transcript

  1. ABOUT ME Learning programming for the last 11 years Did

    Java for around 8 years Started learning Ruby ~3 years back ♥ Ruby ♥ the Ruby community Also learning some CoffeeScript and Scala http://rockyj.in @whatsuprocky
  2. CONCURRENCY? Concurrency is when two tasks can start, run, and

    complete in overlapping time periods Concurrency can be implemented even in single processing units to speed things up Concurrency is non-deterministic Whereas a parallel program is one that merely runs on multiple processors, with the goal of hopefully running faster than it would on a single CPU
  3. THREADS VS PROCESSESS Threads are light weight processes that run

    in the same memory context Ruby has Green Threads which are managed by the Ruby process JRuby has real OS thread that run parallel to the parent thread
  4. SAMPLE UNICORN SETUP 15 Unicorns = 15 Processes 1 Unicorn

    Process ~= 150 MB 15 Processes ~= 2 GB RAM* Scaling this means more processes = more memory = more money Also, If you are CPU bound you want to use no more unicorn processes than you have cores, otherwise you overload the system and slow down the scheduler.
  5. CONCURRENCY IS GOOD JRuby + Puma / Torquebox High-Scalability with

    less memory Resque / Sidekiq More workers and faster processing with less memory
  6. SO IS IT ALL DOOM AND GLOOM? No! Most Rails

    applications are IO bound With MRI you are always thread safe MRI is getting faster and GC is getting better Processes management is optimized Passenger is using a hybrid - evented + threaded / process architecture
  7. RUN CODE ON MRI & JRUBY array = [] 5.times.map

    do Thread.new do #Init 5 threads 1000.times do array << nil #In each thread add 1000 elements to the Ar end end end.each(&:join) puts array.size
  8. WHAT ABOUT RAILS config.threadsafe! def threadsafe! @preload_frameworks = true @cache_classes

    = true @dependency_loading = false @allow_concurrency = true self end
  9. BAD COUNTER CODE class PagesController < ApplicationController @counter = 0

    class << self attr_accessor :counter end #Classic read-modify-write problem def index counter = self.class.counter # read sleep(0.1) counter += 1 #update sleep(0.1) self.class.counter = counter # write users = User.all puts "-----------" + self.class.counter.to_s + "------------" end end
  10. UGLY SYNCHRONIZED CODE class PagesController < ApplicationController @counter = 0

    @semaphore = Mutex.new class << self attr_accessor :counter attr_accessor :semaphore end def index #counter = self.class.counter # read sleep(0.1) self.class.semaphore.synchronize { self.class.counter += 1 #update } sleep(0.1) #self.class.counter = counter # write users = User.all puts "-----------" + self.class.counter.to_s + "------------" end end
  11. SAFE CONCURRENCY Don't do it. If you must do it,

    don't share data across threads. If you must share data across threads, don't share mutable data. If you must share mutable data across threads, synchronize access to that data.
  12. ATOMIC COUNTER java_import 'java.util.concurrent.atomic.AtomicInteger' class PagesController < ApplicationController @counter =

    AtomicInteger.new(1) class << self attr_accessor :counter end def index sleep(0.1) counter = self.class.counter.getAndIncrement() #update sleep(0.1) users = User.all puts "-----------------" + counter.to_s + "-----------------" end end
  13. ALL THIS SUCKS! 95% of syncronized code is broken. The

    other 5% is written by Brian Goetz. - Venkat Subramaniam
  14. THE ACTOR MODEL Introduced by Carl Hewitt in 1973 Contributions

    by a lot of scholars and universities Popularized by Erlang, now in Scala Simple and high-level abstractions for concurrency and parallelism Objects are Actors each with their own state which is never shared Communication happens through messages Very lightweight event-driven processes (approximately 2.7 million actors per GB RAM [Akka])
  15. THE ACTOR MODEL -2 Easier to deal with humans than

    with threads Like humans, Actors communicate via messages No state sharing, communicate via immutable messages
  16. SUMMARY Concurrency is the need of the hour MRI is

    thread safe by default due to GIL / GVL JRuby gives you real concurrency (RBX as well) With power comes responsibility Don't worry, concurrency can be easy if you follow the ground rules If you want to write concurrent code yourself, use Actors * I did not cover STM (provided by Clojure)
  17. THANK YOU! QUESTIONS #A lot of this content has been

    taken from blogs, wikis and books. I do not claim it is my own and I wholeheartedly thank everyone who helped me with this presentation.