我正在尝试对以下代码进行基准测试,
Rate.rate_by_service方法,执行一些DB调用/处理并返回值
mutex = Mutex.new
thread_arr = []
puts Benchmark.measure{
1000.times do |i|
services.each_with_index do |service_obj,index|
thread_arr[index] = Thread.new {
mutex.synchronize {
rate << Rate.rate_by_service(service_obj,@package,@from,@to,@credentials) #does database calls / calcualtions and returns a value
}
}
#rate <<
end
thread_arr.each {|t| t.join}
end
}
我观察到的奇怪之处在于多线程版本比普通版本(没有线程)慢
以下是基准测试结果。
#threading
4.870000 0.490000 5.360000 ( 6.846712)
5.300000 0.520000 5.820000 ( 7.550946)
4.640000 0.480000 5.120000 ( 6.720078)
4.580000 0.460000 5.040000 ( 6.344415)
4.510000 0.450000 4.960000 ( 6.312238)
#no threading
3.610000 0.240000 3.850000 ( 4.088772)
3.360000 0.200000 3.560000 ( 3.721254)
3.380000 0.190000 3.570000 ( 3.795252)
3.500000 0.200000 3.700000 ( 4.156553)
3.580000 0.210000 3.790000 ( 4.183601)
我有什么不对劲吗?任何人都可以详细说明为什么会发生这种行为。
我正在使用ruby 2.0,rails Rails 4.2.7.1
答案 0 :(得分:3)
每个Thread
的整个可执行块都被同步,使代码完全同步,但在线程创建和上下文切换上引入了开销。你有什么期望?
要使其异步,应该只同步原始数组更新:
1000.times do |_|
services.map do |service_obj|
Thread.new do
result = Rate.rate_by_service(...)
mutex.synchronize { rate << result }
end
end.each(&:join)
end
请注意,数据库查询Rate.rate_by_service
是在互斥锁同步之外进行的。