1

我们的程序创建了一个主哈希,其中每个键都是一个代表 ID 的符号(大约 10-20 个字符)。每个值都是一个空哈希。

主哈希有大约 80 万条记录。

然而,我们看到 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
4

1 回答 1

1

我会说这对 Ruby 来说是正常的。我没有每个数据结构使用的空间的度量标准,但一般来说,基本的Ruby 在这种大型结构上效果不佳。它必须考虑到键和值可以是任何类型的对象的事实,尽管这对于高级编码非常灵活,但当您不需要这种任意控制时效率低下。

如果我在 irb 中这样做

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

我得到一个使用 197 Mb 的进程。

您的进程占用了更多空间,因为它在处理过程中创建了大量哈希 - 每行一个。Ruby 最终会清理掉——但这不会立即发生,内存也不会立即返回给操作系统。

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

于 2013-03-19T08:51:23.073 回答