2013-03-19 72 views
1

我们的程序创建一个主散列,其中每个键都是表示ID(大约10-20个字符)的符号。每个值都是一个空的散列。Ruby中的内存使用率高:500B正常的空散列?

主散列有大约800K条记录。

但是我们看到ruby的内存几乎达到了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

哈希不是内存中唯一的东西,是吗? – 2013-03-19 05:14:02

+0

我们正在阅读文件的每一行,将尽快发布代码。谢谢。 – Crashalot 2013-03-19 05:42:37

+0

更新了代码 – Crashalot 2013-03-19 06:35:59

回答

1

我会说这是正常的红宝石。我没有关于每个数据结构使用的空间的指标,但总的来说基本的 Ruby在这种大型结构上工作得很差。它必须考虑到键和值可以是任何类型的对象,虽然这对于高级编码非常灵活,但如果不需要这种任意控制,效率会很低。

如果我这样做是IRB

h = {} 
800000.times { |x| h[("test" + x.to_s).to_sym] = {} } 

我与使用197 MB的过程。

由于在处理过程中创建了大量的哈希值,因此您的进程占用了更多的空间 - 每一行都有一个哈希值。 Ruby最终将清除 - 但这不会立即发生,并且内存也不会立即返回到操作系统。

编辑:我应该补充一点,我一直在使用Ruby中的各种大型数据结构 - 如果您需要它们的一般方法是在本机扩展(或ffi)中寻找代码可以利用例如,在数组中使用受限类型。宝石narray就是数值数组,向量,矩阵等的一个很好的例子。

+0

谢谢,尼尔。任何关于字符串数组的建议?还有一种方法可以在Ruby中标记GC的对象吗?当你说它没有立即返回到操作系统时,需要多长时间?如果我们在标记对象(假设可能)清理之后睡了一小段时间,我们是否可以假设内存使用量会恢复到正常水平? – Crashalot 2013-03-19 09:26:08

+0

我不知道你的问题的答案,我对这一层的语言不够熟悉。对我来说,它看起来像你正在尝试创建代表你的slurped文件的东西,并且一旦完成就可以被查询和/或处理。如果是这样,我可能会推荐而不是与Ruby内部战斗,考虑使用像SQLite这样的内存驱动程序(有一个使用SQLite的Ruby库)。它可能会以更好的内存占用量和性能特点为您提供所需的功能。 – 2013-03-19 09:53:28