执行速度差异的原因是什么?

t_s*_*cho 7 ruby python

我写了一个快速的Python脚本来比较两个文件,每个文件包含无序的哈希值,以验证两个文件除了顺序之外是否相同.然后我用Ruby重写了它以用于教育目的.

Python实现需要几秒钟,而Ruby实现需要大约4分钟.

我有一种感觉,这很可能是由于我缺乏Ruby知识,对我做错了什么想法?

环境是Windows XP x64,Python 2.6,Ruby 1.8.6

蟒蛇

f = open('c:\\file1.txt', 'r')

hashes = dict()

for line in f.readlines():
    if not line in hashes:
        hashes[line] = 1
    else:
        hashes[line] += 1


print "Done file 1"

f.close()

f = open('c:\\file2.txt', 'r')

for line in f.readlines():
    if not line in hashes:
        print "Hash not found!"
    else:
        hashes[line] -= 1

f.close()

print "Done file 2"

num_errors = 0

for key in hashes.keys():
    if hashes[key] != 0:
        print "Uneven hash count: %s" % key
        num_errors += 1

print "Total of %d mismatches found" % num_errors
Run Code Online (Sandbox Code Playgroud)

红宝石

file = File.open("c:\\file1.txt", "r")
hashes = {}

file.each_line { |line|
  if hashes.has_key?(line)
    hashes[line] += 1
  else
    hashes[line] = 1
  end
}

file.close()

puts "Done file 1"

file = File.open("c:\\file2.txt", "r")

file.each_line { |line|
  if hashes.has_key?(line)
    hashes[line] -= 1
  else
    puts "Hash not found!"
  end
}

file.close()

puts "Done file 2"

num_errors = 0
hashes.each_key{ |key|
  if hashes[key] != 0
    num_errors += 1
  end
}

puts "Total of #{num_errors} mismatches found"
Run Code Online (Sandbox Code Playgroud)

编辑为了给出规模的概念,每个文件都很大,超过90万个哈希值.

进展

使用nathanvda的建议,这是优化的ruby脚本:

f1 = "c:\\file1.txt"
f2 = "c:\\file2.txt"

hashes = Hash.new(0)

File.open(f1, "r") do |f|
  while line = f.gets
    hashes[line] += 1
  end
end  

not_founds = 0

File.open(f2, "r") do |f|
  while line = f.gets
    if hashes.has_key?(line)
      hashes[line] -= 1
    else
      not_founds += 1
    end
  end
end

num_errors = hashes.values.to_a.select { |z| z != 0}.size   

puts "Total of #{not_founds} lines not found in file2"
puts "Total of #{num_errors} mismatches found"
Run Code Online (Sandbox Code Playgroud)

在使用Ruby 1.8.7的Windows上,原始版本需要250秒,优化版本需要223.

在Linux VM上!运行ruby 1.9.1,原始版本在81秒内运行,大约是Windows 1.8.7的1/3.有趣的是,优化版本需要89秒才能更长时间.请注意,由于内存限制,line = ...是必需的.

在使用Ruby 1.9.1的Windows上,原始版本需要457秒,优化版本需要543秒.

在使用jRuby的Windows上,原始版本需要45秒,优化版本需要43秒.

我对结果感到有些惊讶,我期待1.9.1比1.8.7更好.

Joh*_*ooy 5

这可能是因为Python中的dicts比Ruby中的哈希要快得多

我刚刚运行了一个快速测试,在Ruby1.8.7中构建一个12345678项的哈希值是Python的3倍.Ruby1.9大约是Python的两倍.

这是我测试
python的方式

$ time python -c "d={}
for i in xrange(12345678):d[i]=1"
Run Code Online (Sandbox Code Playgroud)

红宝石

$ time ruby -e "d={};12345678.times{|i|d[i]=1}"
Run Code Online (Sandbox Code Playgroud)

但不足以说明您的差异.

也许文件I/O值得研究 - 注释掉所有哈希代码并查看空循环在文件上运行多长时间.

这是Python中使用defaultdict和上下文管理器的另一个版本

from collections import defaultdict
hashes = defaultdict(int)

with open('c:\\file1.txt', 'r') as f:
    for line in f:
        hashes[line] += 1

print "Done file 1"

with open('c:\\file2.txt', 'r') as f:
    for line in f:
        if line in hashes:
            hashes[line] -= 1
        else:
            print "Hash not found!"

print "Done file 2"

num_errors = 0
for key,value in hashes.items():  # hashes.iteritems() might be better here
    if value != 0:
        print "Uneven hash count: %s" % key
        num_errors += 1

print "Total of %d mismatches found" % num_errors
Run Code Online (Sandbox Code Playgroud)


Car*_*icz 5

我发现Ruby的参考实现(好吧,Ruby)是(非科学地说)狗慢.

如果您有机会,请尝试在JRuby下运行您的程序!查尔斯·纳特(Charles Nutter)和其他太阳人声称自己大幅加速了Ruby.

我对你的结果最感兴趣.

  • 我尝试了jRuby,虽然它比1.8.6解释器快了很多,但在45秒左右它仍然比Python慢​​了3倍(~15s) (4认同)
  • Ruby 1.8.6尤其不是很快.而且有问题的Python版本相当新一些.Ruby 1.9肯定会更好. (2认同)