Skip to content

Instantly share code, notes, and snippets.

@fidelisrafael
Last active January 22, 2019 03:18
Show Gist options
  • Save fidelisrafael/f46609db24a5f6ebbf87e5aa70c55670 to your computer and use it in GitHub Desktop.
Save fidelisrafael/f46609db24a5f6ebbf87e5aa70c55670 to your computer and use it in GitHub Desktop.
This gist compares the use of Threaded and non-Threaded Ruby code to perform IO(Read/Write) on a shared file.
gem 'thread' # gem install thread
require 'thread/pool'
@semaphore = Mutex.new
LOOPS_COUNT = (ENV['LOOPS_COUNT'] || 100).to_i
POOL_SIZE = (ENV['POOL_SIZE'] || LOOPS_COUNT).to_i
def with_thread_without_mutex!(num_loops = 100)
executions = num_loops.times.map do |i|
Thread.new do
count = (File.read('test.txt') || 0).to_i
File.open('test.txt', 'wb') do |file|
file.write((count + 1).to_s)
end
end
end
executions.map(&:join)
end
def with_thread_mutex!(num_loops = 100)
executions = num_loops.times.map do |i|
Thread.new do
@semaphore.synchronize do
count = (File.read('test.txt') || 0).to_i
File.open('test.txt', 'wb') do |file|
# puts "Current count = #{count} | Next count = #{count + 1}"
file.write((count + 1).to_s)
end
end
end
end
executions.map(&:join)
end
def with_thread_pool!(pool_size = 100, num_loops = 100)
pool = Thread.pool(num_loops)
num_loops.times do |i|
pool.process do
@semaphore.synchronize do
count = (File.read('test.txt') || 0).to_i
File.open('test.txt', 'wb') do |file|
# puts "Current count = #{count} | Next count = #{count + 1}"
file.write((count + 1).to_s)
end
end
end
end
pool.shutdown
end
def without_thread!(num_loops = 100)
num_loops.times do |i|
count = (File.read('test.txt') || 0).to_i
File.open('test.txt', 'wb') do |file|
file.write((count + 1).to_s)
end
end
end
def test!(label, value)
if File.read('test.txt').to_i != value
puts "Error for \"#{label}\". The file 'test.txt' must have the exact value 200"
end
end
def truncate!
File.truncate('test.txt', 0)
end
def with_time(label, &block)
start_time = Time.now
yield block if block_given?
end_time = Time.now
puts "Total time for \"#{label}\" ==> #{((end_time - start_time) * 100).round(2)} ms"
end
with_time("with_thread_pool!") do
truncate!
with_thread_pool!(POOL_SIZE, LOOPS_COUNT)
test!("with_thread_pool!", LOOPS_COUNT)
end
sleep(2)
with_time("with_thread_mutex!") do
truncate!
with_thread_mutex!(LOOPS_COUNT)
test!("with_thread_mutex!", LOOPS_COUNT)
end
sleep(2)
with_time("without_thread!") do
truncate!
without_thread!(LOOPS_COUNT)
test!("without_thread!", LOOPS_COUNT)
end
@fidelisrafael
Copy link
Author

➜ ruby test.rb 
Total time for "with_thread_pool!" ==> 13.1 ms [fastest]
Total time for "with_thread_mutex!" ==> 20.57 ms
Total time for "without_thread!" ==> 34.13 ms [slowest]

➜ LOOPS_COUNT=250 ruby test.rb 
Total time for "with_thread_pool!" ==> 96.6 ms
Total time for "with_thread_mutex!" ==> 90.64 ms [fastest]
Total time for "without_thread!" ==> 122.73 ms [slowest]

➜ LOOPS_COUNT=450 ruby test.rb 
Total time for "with_thread_pool!" ==> 169.74 ms
Total time for "with_thread_mutex!" ==> 175.59 ms [slowest]
Total time for "without_thread!" ==> 156.91 ms [fastest]

➜ LOOPS_COUNT=1000 ruby test.rb 
Total time for "with_thread_pool!" ==> 528.86 ms [slowest]
Total time for "with_thread_mutex!" ==> 423.94 ms 
Total time for "without_thread!" ==> 363.41 ms [fastest]

➜ LOOPS_COUNT=1000 ruby test.rb 
Total time for "with_thread_pool!" ==> 420.08 ms
Total time for "with_thread_mutex!" ==> 436.92 ms
Total time for "without_thread!" ==> 418.73 ms

➜ LOOPS_COUNT=1000 ruby test.rb 
Total time for "with_thread_pool!" ==> 416.59 ms 
Total time for "with_thread_mutex!" ==> 514.78 ms [slowest]
Total time for "without_thread!" ==> 389.42 ms [fastest]

➜ LOOPS_COUNT=1500 ruby test.rb 
Total time for "with_thread_pool!" ==> 699.17 ms [slowest]
Total time for "with_thread_mutex!" ==> 572.88 ms [fastest]
Total time for "without_thread!" ==> 632.88 ms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment