Ruby CSV解析内存分配

时间:2016-06-13 14:44:19

标签: ruby-on-rails ruby csv memory out-of-memory

我最近遇到了与Ruby中的大型CSV文件交互的问题。我确信显而易见的解决方案是将这些数据托管在数据库而不是像这样的文件中,但是,我仍然希望找到问题的根源。

我正在与之交互的数据并不过分 - 大约有4300万个数据点。尺寸为8760x5000。我真的需要读取整个CSV文件,以便我可以对它执行一些映射操作,然后将其转储到新文件中。

我试过了两个:

CSV.foreach("file") do |row|    
    master_arr << row
end

master_arr = CSV.read("file")

这两个选项都会触发内存分配错误 - 说明没有足够的内存分配。该错误通常类似于:

C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1798:in `gets': failed to allocate memory (NoMemoryError)
        from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1798:in `block in shift'
        from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1796:in `loop'
        from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1796:in `shift'
        from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1738:in `each'
        from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1122:in `block in foreach'
        from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1273:in `open'
        from C:/RailsInstaller/Ruby2.2.0/lib/ruby/2.2.0/csv.rb:1121:in `foreach'
        from compilation.rb:23:in `<main>'

我不确定为什么这是一个问题。 CSV文件大约为600MB,当我看到我的机器资源时,RAM消耗在故障之前仅增加了大约1GB。在此期间,我仍有大约10GB的可用内存。

如果我创建一个相同大小的数组并用随机数据填充它:

arr1 = Array.new(8760){|i| i+0.111111111111}
arr2 = Array.new(5000){arr1}

将内存存储在内存中没有问题,但如果尝试将其写入CSV文件,则会收到内存分配错误。我浏览了CSV.rb文件,但似乎无法找到任何可能导致此问题的内容。

奇怪的是,这有效:

for i in 0..4999
    CSV.foreach("file") do |row|
        master << row
        break if master_arr.length > 3000
    end
end

但如果我尝试将文件拆分为两个,则不起作用:

CSV.foreach("file_1_2") do |row|    
    master_arr << row
end

CSV.foreach("file_2_2") do |row_1|  
    master_arr << row_1
end

这些物品并没有从记忆中释放出来,但我并不清楚究竟发生了什么。就像我说的,我知道这是一个大文件,它不是最好的选择,但这是一次性的解决方案,我有可用的资源,应该没问题。

1 个答案:

答案 0 :(得分:0)

通常情况下,32位程序的内存限制比64位程序要严格得多,而32位Ruby无法分配与64位版本相同的内存。

如果您可以检查您的安装是否是正确的版本,如果没有,请更新到正确的版本。 ruby -v通常会告诉您正在使用哪一个。