我写了一个快速的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更好.
这可能是因为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)
我发现Ruby的参考实现(好吧,Ruby)是(非科学地说)狗慢.
如果您有机会,请尝试在JRuby下运行您的程序!查尔斯·纳特(Charles Nutter)和其他太阳人声称自己大幅加速了Ruby.
我对你的结果最感兴趣.