Post on 30-Jun-2015
description
CONCURRENCY&
RUBY
RockyJaiswalRubyConfIndia2013
WHYCONCURRENCY?
ABOUTMELearningprogrammingforthelast11years
DidJavaforaround8years
StartedlearningRuby~3yearsback
♥Ruby♥theRubycommunity
AlsolearningsomeCoffeeScriptandScala
http://rockyj.in@whatsuprocky
CONCURRENCY?
Concurrencyiswhentwotaskscanstart,run,andcompleteinoverlappingtimeperiods
Concurrencycanbeimplementedeveninsingleprocessingunitstospeedthingsup
Concurrencyisnon-deterministic
Whereasaparallelprogramisonethatmerelyrunsonmultipleprocessors,withthegoalofhopefullyrunning
fasterthanitwouldonasingleCPU
THREADSVSPROCESSESS
Threadsarelightweightprocessesthatruninthesamememorycontext
RubyhasGreenThreadswhicharemanagedbytheRubyprocess
JRubyhasrealOSthreadthatrunparalleltotheparentthread
THREADSINRUBY
SAMPLEUNICORNSETUP
15Unicorns=15Processes1UnicornProcess~=150MB15Processes~=2GBRAM*
Scalingthismeansmoreprocesses=morememory=moremoney
Also,IfyouareCPUboundyouwanttousenomoreunicornprocessesthanyouhavecores,otherwiseyouoverloadthesystemandslowdownthescheduler.
CONCURRENCYISGOOD
JRuby+Puma/Torquebox
High-Scalabilitywithlessmemory
Resque/Sidekiq
Moreworkersandfasterprocessingwithlessmemory
SOISITALLDOOMANDGLOOM?
No!
MostRailsapplicationsareIOboundWithMRIyouarealwaysthreadsafeMRIisgettingfasterandGCisgettingbetterProcessesmanagementisoptimizedPassengerisusingahybrid-evented+threaded/processarchitecture
THREAD-SAFETYLETMEGIVEYOUADEMO
AppendingtoArrays:
MRIVersionvs
JRubyVersion
DEMO
RUNCODEONMRI&JRUBY
array=[]5.times.mapdoThread.newdo#Init5threads1000.timesdoarray<<nil#Ineachthreadadd1000elementstotheArrayendendend.each(&:join)putsarray.size
EVENAPPENDINGTOARRAYSISNOTTHREADSAFE!
WHATABOUTRAILS
config.threadsafe!
defthreadsafe!@preload_frameworks=true@cache_classes=true@dependency_loading=false@allow_concurrency=trueselfend
JRUBYONRAILS
DEMO
BADCOUNTERCODE
classPagesController<ApplicationController@counter=0class<<selfattr_accessor:counterend#Classicread-modify-writeproblemdefindexcounter=self.class.counter#readsleep(0.1)counter+=1#updatesleep(0.1)self.class.counter=counter#writeusers=User.allputs"-----------"+self.class.counter.to_s+"------------"endend
UGLYSYNCHRONIZEDCODE
classPagesController<ApplicationController@counter=0@semaphore=Mutex.newclass<<selfattr_accessor:counterattr_accessor:semaphoreenddefindex#counter=self.class.counter#readsleep(0.1)self.class.semaphore.synchronize{self.class.counter+=1#update}sleep(0.1)#self.class.counter=counter#writeusers=User.allputs"-----------"+self.class.counter.to_s+"------------"endend
RAILS4ISCONCURRENCYENABLEDBYDEFAULT
CONCURRENCYINTRODUCES
RaceConditionsDeadlocksStarvation
etc.
BUTGIVESYOUSpeed
LessMemoryUsage
SAFECONCURRENCY
Don'tdoit.Ifyoumustdoit,don'tsharedataacrossthreads.Ifyoumustsharedataacrossthreads,don'tsharemutabledata.Ifyoumustsharemutabledataacrossthreads,synchronizeaccesstothatdata.
THREADSAFETYINJRUBY
LOCKS
ATOMICITY
IMMUTABILITY
ATOMICCOUNTER
java_import'java.util.concurrent.atomic.AtomicInteger'
classPagesController<ApplicationController@counter=AtomicInteger.new(1)class<<selfattr_accessor:counterend
defindexsleep(0.1)counter=self.class.counter.getAndIncrement()#updatesleep(0.1)users=User.allputs"-----------------"+counter.to_s+"-----------------"endend
ALLTHISSUCKS!
95%ofsyncronizedcodeisbroken.Theother5%iswrittenbyBrianGoetz.-VenkatSubramaniam
ENTERACTOR
THEACTORMODEL
IntroducedbyCarlHewittin1973Contributionsbyalotofscholarsanduniversities
PopularizedbyErlang,nowinScala
Simpleandhigh-levelabstractionsforconcurrencyandparallelismObjectsareActorseachwiththeirownstatewhichisneversharedCommunicationhappensthroughmessagesVerylightweightevent-drivenprocesses(approximately2.7millionactorsperGBRAM[Akka])
THEACTORMODEL-2
Easiertodealwithhumansthanwiththreads
Likehumans,Actorscommunicateviamessages
Nostatesharing,communicateviaimmutablemessages
IMPLEMENTATIONS
PRODUCERCONSUMERPROBLEM
DemowithJRuby+LocksDemowithJRuby+Celluloid
PRODUCERCONSUMERwithlocks
HTTPS://GIST.GITHUB.COM/ROCKY-JAISWAL/5847810
PRODUCERCONSUMERwithactors
HTTPS://GIST.GITHUB.COM/ROCKY-JAISWAL/5847814
SUMMARY
ConcurrencyistheneedofthehourMRIisthreadsafebydefaultduetoGIL/GVLJRubygivesyourealconcurrency(RBXaswell)WithpowercomesresponsibilityDon'tworry,concurrencycanbeeasyifyoufollowthegroundrulesIfyouwanttowriteconcurrentcodeyourself,useActors
*IdidnotcoverSTM(providedbyClojure)
THANKYOU!
QUESTIONS
#Alotofthiscontenthasbeentakenfromblogs,wikisandbooks.Idonotclaimitismy
ownandIwholeheartedlythankeveryonewhohelpedmewiththispresentation.