今天尝试了一下用 Thread 并行查询,发现有效果的
我在 Ruby China 的代码里面找了个无法命中索引的 MongoDB 查询场景(平均每个 105ms 左右),创建 5 个线程来执行。 大家都知道 Ruby 存在 GIL (Python 也是),但 GIL 不会影响到 I/O (数据库查询,文件读写,网络请求) 的动作。
def index
threads = []
5.times.each do
threads << Thread.new do
@total_count = Topic.where(:_id.ne => Time.now.to_i).count
end
end
threads.each(&:join)
render text: "ok"
end
Started GET "/topics" for 127.0.0.1 at 2015-05-24 02:39:46 +0800
Processing by TopicsController#index as HTML
MOPED: command={:count=>"topics", :query=>{"_id"=>{"$ne"=>1432406386}}} runtime: 103.6620ms
MOPED: command={:count=>"topics", :query=>{"_id"=>{"$ne"=>1432406386}}} runtime: 105.8040ms
MOPED: command={:count=>"topics", :query=>{"_id"=>{"$ne"=>1432406386}}} runtime: 104.6600ms
MOPED: command={:count=>"topics", :query=>{"_id"=>{"$ne"=>1432406386}}} runtime: 105.9680ms
MOPED: command={:count=>"topics", :query=>{"_id"=>{"$ne"=>1432406386}}} runtime: 107.4280ms
Rendered text template (0.1ms)
Completed 200 OK in 116ms (Views: 0.6ms)
总耗时 126ms
, 如果是顺序执行的话,应该是 105 * 5 = 525ms
看起来,如果场景允许并行查询的话,这么做是有意义的。
顺便提一下,这里 Thread 的并发数量和 Puma 的 thread 数量配置无关,我尝试了用 Unicorn 或 Puma -t 0:1 启动,效果依然和上面一样。