Ruby Concurrency & Threads
Anup Nivargi
I <3 Ruby!
Concurrency V Parallelism
Ruby Implementations
MRI, JRuby, Rubinius etc..
Threads In Ruby
thread_example.rb
def thread1
100.times do |i|
puts "In Thread 1"
end
end
def thread2
100.times do
puts "In Thread 2"
end
end
t1 = Thread.new { thread1 }
t2 = Thread.new { thread2 }
t1.join
t2.join
CPU Intensive Tasks
factorial.rb
require 'benchmark'
def factorial_with_range(range)
(1..range).to_a.each_slice(range/4).to_a.each do |elements|
elements.each {|element| factorial(element) }
end
end
def factorial_with_range_threaded(range)
threads = []
(1..range).to_a.each_slice(range/4).to_a.each do |elements|
threads << Thread.new do
elements.each{|element| factorial(element) }
end
end
threads.each(&:join)
end
factorial.rb (contd)
def factorial(n)
(1..n).to_a.inject(:*)
end
Benchmark.bm(30) do |bm|
[4000, 5000].each do |num|
bm.report("Single Threaded #{num}") do
factorial_with_range(num)
end
bm.report("Multi Threaded #{num}") do
factorial_with_range_threaded(num)
end
end
end
Ruby MRI Benchmarks
user system total real
Single Threaded 4000 10.230000 0.100000 10.330000 ( 10.419738)
Multi Threaded 4000 10.340000 0.330000 10.670000 ( 10.770526)
Single Threaded 5000 18.960000 0.490000 19.450000 ( 19.601181)
Multi Threaded 5000 19.120000 0.730000 19.850000 ( 20.012569)
Rubinius Benchmarks
user system total real
Single Threaded 4000 6.228000 0.139000 6.367000 ( 6.413544)
Multi Threaded 4000 0.003000 0.000000 0.003000 ( 4.565215)
Single Threaded 5000 11.519000 0.306000 11.825000 ( 11.937241)
Multi Threaded 5000 0.002000 0.000000 0.002000 ( 9.129658)
Why?
GIL or GVL
in Ruby MRI
But, there is a catch!
IO Intensive Task
server.rb
require "webrick"
server = WEBrick::HTTPServer.new :Port => 8000
server.mount_proc "/" do |req, res|
sleep 1
res.body = "Hello World"
end
trap 'INT' do server.shutdown end
server.start
service.rb
require "benchmark"
require "net/http"
def fetch(count)
uri = URI.parse("http://localhost:8000/")
threads = []
count.times do
threads << Thread.new do
Net::HTTP.get_response(uri)
end
end
threads.each(&:join)
end
Benchmark.bm(30) do |bm|
bm.report("IO Service"){ fetch(20) }
end
Rubinius Benchmarks
user system total real
IO Service 0.014000 0.002000 0.016000 ( 1.037461)
Ruby MRI Benchmarks
user system total real
IO Service 0.050000 0.030000 0.080000 ( 1.070662)
Ahhhh!
Threading Caveats
Conclusion
Online References
Code : https://github.com/anupnivargi/experiments/tree/master/threads
https://blog.engineyard.com/2013/ruby-concurrency
http://speakmy.name/2013/04/02/concurrent-programming-and-threads-in-ruby-reading-list/
https://blog.engineyard.com/2011/ruby-concurrency-and-you
http://merbist.com/2011/02/22/concurrency-in-ruby-explained/
Questions?
Anup Nivargi
@therealnoop
anupnivargi@gmail.com
Thank You!
Ruby Concurrency & Threads

Ruby Concurrency & Threads