Last active
August 29, 2015 14:02
-
-
Save billdueber/7c9a37ce2c2f09e97b64 to your computer and use it in GitHub Desktop.
Demonstration of MRI thread pools failing to do all their work
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'concurrent' | |
require 'thread' | |
# A simple safe array implementation. | |
class SafeArray | |
def initialize | |
@write_mutex = Mutex.new | |
@arr = [] | |
end | |
def <<(x) | |
@write_mutex.synchronize do | |
@arr << "#{x}" | |
end | |
end | |
def size | |
@write_mutex.synchronize do | |
@arr.size | |
end | |
end | |
end | |
# Get a pool with three threads and a safe array | |
pool = Concurrent::FixedThreadPool.new(3, :overflow_policy => :caller_runs) | |
sa = SafeArray.new | |
sa << "Starting..." | |
# Stick the numbers 0..4 in the safe array | |
5.times do |x| | |
pool.post do | |
sa << x | |
end | |
end | |
# If you pass a numeric argument, we sleep that long | |
# to show that a forced pause allows the threads time | |
# to terminate normally, but the combination of #shutdown | |
# and #wait_for_termination doesn't | |
unless ARGV[0].nil? | |
wait_seconds = ARGV[0].to_f | |
sleep wait_seconds | |
end | |
# Do an orderly shutdown | |
pool.shutdown | |
pool.wait_for_termination(500) | |
puts "Total size is #{sa.size}" | |
# Run this in sets of three, once without a delay and once with a 0.25-second delay | |
# | |
# > ruby -v | |
# ruby 2.1.0dev (2013-11-23 trunk 43807) [x86_64-darwin11.0] | |
# > for i in 1 2 3; do ruby thread_pool_failure.rb; done | |
# Total size is 1 | |
# Total size is 1 | |
# Total size is 1 | |
# | |
# Oops! Looks like the threads aren't getting their data into the safe array -- just the "Starting..." string. | |
# Suppose we force a quarter-second delay before calling #shutdown? | |
# | |
# > for i in 1 2 3; do ruby thread_pool_failure.rb 0.25; done | |
# Total size is 6 | |
# Total size is 6 | |
# Total size is 6 | |
# JRuby doesn't exhibit this behavior; it gets it right every time | |
# > ruby -v | |
# jruby 1.7.10 (1.9.3p392) 2014-01-09 c4ecd6b on Java HotSpot(TM) 64-Bit Server VM 1.8.0-b132 +indy [darwin-x86_64] | |
# > for i in 1 2 3; do ruby thread_pool_failure.rb; done | |
# Total size is 6 | |
# Total size is 6 | |
# Total size is 6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment