Ruby 求教关于 Ruby 的多线程问题

mclxly · 发布于 2015年01月09日 · 最后由 spacewander 回复于 2015年01月19日 · 1943 次阅读
11794

问题1:为啥多线程比单线程慢这么多(大约1分钟)? 问题2:为啥Ruby的MD5计算这么慢?同样的单线程版程序我用php/go写都只用大约1分钟。难道我使用不对?

多线程版:

#!/usr/bin/ruby
require 'digest/md5'

def fexe(value="")
    digest = Digest::MD5.hexdigest(value)

    for i in 1..10000
        digest = Digest::MD5.hexdigest(value)
    end
end

count = 0
arr = []

msg = "http://php.net/manual/en/function.printf.php";

for i in 1..10000    
   arr[i-1] = Thread.new {
      fexe(msg)
   } 
end

puts "size: #{arr.size}"

arr.each {|t| t.join; }
puts "done!"

输出:

size: 10000
done!

real    5m27.146s
user    5m19.881s
sys     0m2.870s

单线程版:

#!/usr/bin/ruby
require 'digest/md5'

def fexe(value="")
    digest = Digest::MD5.hexdigest(value)

    for i in 1..10000
        digest = Digest::MD5.hexdigest(value)
    end
end

count = 0
arr = []

msg = "http://php.net/manual/en/function.printf.php";

for i in 1..10000
    fexe(msg)
end

puts "size: #{arr.size}"
puts "done!"

输出:

size: 0
done!

real    4m16.798s
user    4m16.175s
sys     0m0.189s

共收到 16 条回复
22014d

为啥? 因为它是 Ruby !!!

4120

问题1:GIL

254

$ time ruby md.rb size: 10000 done!

real 0m40.578s user 2m23.146s sys 0m2.253s

$ time ruby mds.rb size: 0 done!

real 1m24.515s user 1m27.306s sys 0m0.742s

用jruby就没这烦恼了

11794

#2楼 @kungs 有空我试试Python的多线程,看是不是也有GIL问题。但我觉得还有个可能是Thread对象太重。

#3楼 @liprais JRuby好比PHP的HHVM,的确跑的快。

1411

楼主可以解释下这段代码是要做什么吗? for i in 1..10000 arr[i-1] = Thread.new { fexe(msg) } end

3a5cee

ruby是不支持真正的多线程的。@mclxly MRuby是thread not safe, 如果确实想用,最好用JRuby。

1667

#6楼 @rocLv 应该倒过来说吧, MRuby 是本身是 thread safe, 个人写的代码不管是 MRuby 还是 JRuby 都需要自己注意 thread safe

254

#5楼 @zeeler 我猜是把线程对象放进数组了

96

c ruby是单线程的。 它所实现的多线程相当于纤程, 随便起多少个线程,最终只能占用cpu一个核心。 需要使用多个cpu的多线程,请换成 jruby. 或者自己用c/或者c++封装一个gem来多线程处理md5. 然后c ruby调用.

2880

呃, 主要是 Digest::MD5.hexdigest 的实现多生成了一个重量级对象啦, 你先 Digest::MD5.new 就好了. 下面这个单线程的代码大约 1 分半钟

#!/usr/bin/ruby
require 'digest/md5'

M = Digest::MD5.new
def fexe value=""
    digest = M.hexdigest(value)
    10000.times {
      digest = M.hexdigest(value)
    }
end

count = 0
arr = []
msg = "http://php.net/manual/en/function.printf.php";

10000.times {
  fexe msg
}

puts "size: #{arr.size}"
puts "done!"
2880

#9楼 @zyfire Ruby 本身就是封装的 C 写的 md5, 和其他语言实现一样

96

是封装的 C 写的 md5, 但没有封装成多线程同步计算的。

3a5cee

@serco Maz在 <代码的未来>中专门讨论了thread safe, MRuby默认不是thread safe的

1667

#14楼 @rocLv 没有看过 <代码的未来>,能详细说一下嘛? 目前我的理解是,MRI下,所有C实现的Ruby核心库部分是线程安全的,因为有GVL在 Ruby实现的部分标准库,用Ruby写的其他项目,不一定是线程安全的

11147

#11楼 @luikore 发现多线程版本开的线程越少,性能越接近于单线程。也许是因为这是个CPU bound的程序。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册