在 Ruby 中分配内存失败(No MemoryError)?
Posted
技术标签:
【中文标题】在 Ruby 中分配内存失败(No MemoryError)?【英文标题】:Failed to allocate memory (No MemoryError) in Ruby? 【发布时间】:2014-06-24 14:31:14 【问题描述】:我编写了一个简单的脚本,它应该读取整个目录,然后通过去掉 html 标签将 HTML 数据解析为普通脚本,然后将其写入一个文件。
我有 8GB 内存和大量可用的虚拟内存。当我这样做时,我有超过 5GB 的可用 RAM。目录中最大的文件为 3.8 GB。
脚本是
file_count = 1
File.open("allscraped.txt", 'w') do |out1|
for file_name in Dir["allParts/*.dat"] do
puts "#file_name#:#file_count"
file_count +=1
File.open(file_name, "r") do |file|
source = ""
tmp_src = ""
counter = 0
file.each_line do |line|
scraped_content = line.gsub(/<.*?\/?>/, '')
tmp_src << scraped_content
if (counter % 10000) == 0
tmp_src = tmp_src.gsub( /\s2,/, "\n" )
source << tmp_src
tmp_src = ""
counter = 0
end
counter += 1
end
source << tmp_src.gsub( /\s2,/, "\n" )
out1.write(source)
break
end
end
end
完整的错误代码是:
realscraper.rb:33:in `block (4 levels) in <main>': failed to allocate memory (No
MemoryError)
from realscraper.rb:27:in `each_line'
from realscraper.rb:27:in `block (3 levels) in <main>'
from realscraper.rb:23:in `open'
from realscraper.rb:23:in `block (2 levels) in <main>'
from realscraper.rb:13:in `each'
from realscraper.rb:13:in `block in <main>'
from realscraper.rb:12:in `open'
from realscraper.rb:12:in `<main>'
其中第 27 行是 file.each_line do |line|
,第 33 行是 source << tmp_src
。失败的文件是最大的文件 (3.8 GB)。这里有什么问题?即使我有足够的内存,为什么我会收到此错误?还有怎么解决?
【问题讨论】:
失败的文件有多大?它是否有换行符? 首先添加日志以查看它是在特定文件上还是在特定时间后失败。如果它总是在同一个文件中失败,请尝试在只有该文件的文件夹上运行它。它将为您提供有价值的信息。 @Patru,感谢您的提醒,我更新了我的答案。这是最大的一个。 @Martin,正如我所说的它是最高的,我自己尝试了一下,得到了同样的错误。++counter
不是有效的 Ruby(至少它不会像您认为的那样做)。
【参考方案1】:
问题出在这两行:
source << tmp_src
source << tmp_src.gsub( /\s2,/, "\n" )
当您读取一个大文件时,您会在内存中慢慢增长一个非常大的字符串。
最简单的解决方案是根本不使用这个临时的source
字符串,而是将结果直接写入文件。只需将这两行替换为:
# source << tmp_src
out1.write(tmp_src)
# source << tmp_src.gsub( /\s2,/, "\n" )
out1.write(tmp_src.gsub( /\s2,/, "\n" ))
这样您就不会在内存中创建任何大的临时字符串,并且它应该可以更好(更快)地工作。
【讨论】:
以上是关于在 Ruby 中分配内存失败(No MemoryError)?的主要内容,如果未能解决你的问题,请参考以下文章