我们的程序创建一个主哈希,其中每个键是一个代表ID的符号(大约10-20个字符)。每个值都是一个空哈希值。
主哈希有大约800K记录。
但我们看到红宝石内存几乎达到400MB。
这表明每个键/值对(符号+空哈希)每个消耗约500B。
红宝石是正常的吗?
以下代码:
def load_app_ids
cols = get_columns AppFile
id_col = cols[:application_id]
each_record AppFile do |r|
@apps[r[id_col].intern] = {}
end
end
# Takes a line, strips the record seperator, and return
# an array of fields
def split_line(line)
line.gsub(RecordSeperator, "").split(FieldSeperator)
end
# Run a block on each record in a file, up to
# @limit records
def each_record(filename, &block)
i = 0
path = File.join(@dir, filename)
File.open(path, "r").each_line(RecordSeperator) do |line|
# Get the line split into columns unless it is
# a comment
block.call split_line(line) unless line =~ /^#/
# This import can take a loooong time.
print "\r#{i}" if (i+=1) % 1000 == 0
break if @limit and i >= @limit
end
print "\n" if i > 1000
end
# Return map of column name symbols to column number
def get_columns(filename)
path = File.join(@dir, filename)
description = split_line(File.open(path, &:readline))
# Strip the leading comment character
description[0].gsub!(/^#/, "")
# Return map of symbol to column number
Hash[ description.map { |str| [ str.intern, description.index(str) ] } ]
end
答案 0 :(得分:1)
我认为这对Ruby来说是正常的。我没有每个数据结构使用的空间度量标准,但总的来说 basic Ruby在这种大型结构上运行不佳。它必须允许键和值可以是任何类型的对象,尽管这对于高级编码非常灵活,但是当你不需要这种任意控制时效率很低。
如果我在irb中这样做
h = {}
800000.times { |x| h[("test" + x.to_s).to_sym] = {} }
我得到了一个使用了197 Mb的过程。
您的进程占据了更多空间,因为它在处理期间创建了大量哈希值 - 每行一个哈希值。 Ruby最终会清理 - 但这不会立即发生,并且内存也不会立即返回到操作系统。
编辑:我应该补充一点,我一直在使用Ruby中的各种大型数据结构 - 如果你需要它们的一般方法是找到用本机扩展(或ffi)编码的代码,代码可以利用它们例如,数组中的受限类型。对于数值数组,向量,矩阵等,gem narray
就是一个很好的例子。