Concurrency & Ruby

1,146 views

Published on

Slides for my talk at RubyConf India 2013

Published in: Technology

Concurrency & Ruby

  1. 1. CONCURRENCY&RUBYRocky JaiswalRubyConf India 2013
  2. 2. WHY CONCURRENCY?
  3. 3. ABOUT MELearning programming for the last 11 yearsDid Java for around 8 yearsStarted learning Ruby ~3 years back♥ Ruby♥ the Ruby communityAlso learning some CoffeeScript and Scalahttp://rockyj.in@whatsuprocky
  4. 4. CONCURRENCY?Concurrency is when two tasks can start, run, andcomplete in overlapping time periodsConcurrency can be implemented even in singleprocessing units to speed things upConcurrency is non-deterministicWhereas a parallel program is one that merely runs onmultiple processors, with the goal of hopefully runningfaster than it would on a single CPU
  5. 5. THREADS VS PROCESSESSThreads are light weight processes that run in the samememory contextRuby has Green Threads which are managed by the RubyprocessJRuby has real OS thread that run parallel to the parentthread
  6. 6. THREADS IN RUBY
  7. 7. SAMPLE UNICORN SETUP15 Unicorns = 15 Processes1 Unicorn Process ~= 150 MB15 Processes ~= 2 GB RAM*Scaling this means more processes = more memory =more moneyAlso, If you are CPU bound you want to use no moreunicorn processes than you have cores, otherwise youoverload the system and slow down the scheduler.
  8. 8. CONCURRENCY IS GOODJRuby + Puma / TorqueboxHigh-Scalability with less memoryResque / SidekiqMore workers and faster processing with less memory
  9. 9. SO IS IT ALL DOOM AND GLOOM?No!Most Rails applications are IO boundWith MRI you are always thread safeMRI is getting faster and GC is getting betterProcesses management is optimizedPassenger is using a hybrid - evented + threaded /process architecture
  10. 10. THREAD-SAFETYLET ME GIVE YOU A DEMOAppending to Arrays:MRI VersionvsJRuby VersionDEMO
  11. 11. RUN CODE ON MRI & JRUBYarray = []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 endend.each(&:join)puts array.size
  12. 12. EVEN APPENDING TO ARRAYS ISNOT THREAD SAFE!
  13. 13. WHAT ABOUT RAILSconfig.threadsafe! def threadsafe! @preload_frameworks = true @cache_classes = true @dependency_loading = false @allow_concurrency = true selfend
  14. 14. JRUBY ON RAILSDEMO
  15. 15. 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 + "------------" endend
  16. 16. 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 + "------------" endend
  17. 17. RAILS 4 IS CONCURRENCYENABLED BY DEFAULT
  18. 18. CONCURRENCY INTRODUCESRace ConditionsDeadlocksStarvationetc.BUT GIVES YOUSpeedLess Memory Usage
  19. 19. SAFE CONCURRENCYDont do it.If you must do it, dont share data acrossthreads.If you must share data across threads, dontshare mutable data.If you must share mutable data across threads,synchronize access to that data.
  20. 20. THREAD SAFETY IN JRUBYLOCKSATOMICITYIMMUTABILITY
  21. 21. ATOMIC COUNTERjava_import java.util.concurrent.atomic.AtomicIntegerclass 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 + "-----------------" endend
  22. 22. ALL THIS SUCKS!95% of syncronized code is broken. The other 5% iswritten by Brian Goetz. - Venkat Subramaniam
  23. 23. ENTER ACTOR
  24. 24. THE ACTOR MODELIntroduced by Carl Hewitt in 1973Contributions by a lot of scholars and universitiesPopularized by Erlang, now in ScalaSimple and high-level abstractions for concurrency andparallelismObjects are Actors each with their own state which is neversharedCommunication happens through messagesVery lightweight event-driven processes (approximately 2.7million actors per GB RAM [Akka])
  25. 25. THE ACTOR MODEL -2Easier to deal with humans than with threadsLike humans, Actors communicate via messagesNo state sharing, communicate via immutable messages
  26. 26. IMPLEMENTATIONS
  27. 27. PRODUCER CONSUMER PROBLEMDemo with JRuby + LocksDemo with JRuby + Celluloid
  28. 28. PRODUCER CONSUMERwith locksHTTPS://GIST.GITHUB.COM/ROCKY-JAISWAL/5847810
  29. 29. PRODUCER CONSUMERwith actorsHTTPS://GIST.GITHUB.COM/ROCKY-JAISWAL/5847814
  30. 30. SUMMARYConcurrency is the need of the hourMRI is thread safe by default due to GIL / GVLJRuby gives you real concurrency (RBX as well)With power comes responsibilityDont worry, concurrency can be easy if you follow theground rulesIf you want to write concurrent code yourself, useActors* I did not cover STM (provided by Clojure)
  31. 31. THANK YOU!QUESTIONS#A lot of this content has been taken from blogs, wikis and books. I do not claim it is myown and I wholeheartedly thank everyone who helped me with this presentation.

×