I'm experimenting to understand a problem in production, so I've thrown this snippet inside a controller action in dev to test:
start = Time.now
num_threads = 6
results = Queue.new
saved_results = []
threads = []
connections = []
semaphore = Mutex.new
# start threads
(1..num_threads).each do |i|
threads << Thread.new do
#semaphore.synchronize { connections << ActiveRecord::Base.connection } # for cleanup?
#ActiveRecord::Base.connection.execute("select sleep(1.6);") # runs sequentially
sleep(1.6) # runs concurrently
result = User.find_by_id(i)
results << [i, result]
end
end
# end option 1 - let everyone finish
threads.each(&:join)
# end option 2 - simulate early exit condition
#while saved_results.count < 3 do saved_results << results.pop end
#threads.each(&:exit)
# cleanup/close open connections?
#connections.select(&:active?).each(&:disconnect!)
elapsed = Time.now - start
render :text => [ elapsed.to_s, saved_results.size, results.size ].join(", ")
sleep(1.6)
executes in approximately 1.6
seconds, as expected.
However, the ActiveRecord select sleep(1.6);
takes 6 * 1.6 = 9.6
seconds, despite mysql console show processlist;
displaying that independent connections are opened for each thread*.
What's going on? Why won't the ActiveRecord queries run concurrently? I've also experienced this in production console.
I do have config.threadsafe!
set in config/environment.rb
. If it matters, I'm using Rails 2.3.
*These connections have to be manually closed? Production always has a lot of open connections that are doing nothing, causing Mysql::Error: Too many connections
. I'll probably submit this issue as a another question.