【发布时间】:2026-01-13 06:25:01
【问题描述】:
我有一个 2.6 GB 的文本文件,其中包含一个数据库表的转储,我正在尝试将其拉入一个逻辑结构,以便所有字段都是唯一的。我用来执行此操作的代码在这里:
class Targetfile
include Enumerable
attr_accessor :inputfile, :headers, :input_array
def initialize(file)
@input_array = false
@inputfile = File.open(file, 'r')
@x = @inputfile.each.count
end
def get_headers
@y = 1
@inputfile.rewind
@input_array = Array.new
@headers = @inputfile.first.chomp.split(/\t/)
@inputfile.each do |line|
print "\n#{@y} / #{@x}"
@y+=1
self.assign_row(line)
end
end
def assign_row(line)
row_array = line.chomp.encode!('UTF-8', 'UTF-8', :invalid => :replace).split(/\t/)
@input_array << Hash[ @headers.zip(row_array) ]
end
def send_build
@input_array || self.get_headers
end
def each
self.send_build.each {|row| yield row}
end
end
类初始化成功,剩下一个 Targetfile 类对象。
问题在于,当我随后调用 get_headers 方法(将文件转换为哈希数组)时,它立即开始减速。
直到项目编号 80,000 左右,我的眼睛才注意到这一点,但随后很明显,文件的每 3-4,000 行,就会发生某种暂停。这种停顿,每次发生时,都需要稍长一点的时间,直到第 100 万行,它需要的时间超过 30 秒。
出于实际目的,我可以将文件切碎以避免此问题,然后将结果列表和唯一的 -that- 组合起来以获得我的最终输出。
但是,从好奇心的角度来看,我并不满意。
谁能告诉我为什么会发生这种停顿,为什么会变长,以及是否有任何方法可以优雅地避免它?真的,我只是想知道它是什么以及它为什么会发生,因为现在我已经注意到了,我在我运行的许多其他 Ruby 脚本中都看到了它,无论是在这台计算机上还是在其他计算机上。
【问题讨论】:
-
你能在一个更小的文件上试试这个吗?它将帮助您确定问题是代码还是文件大小
-
使用
@x = %x(wc -l path/to/file).to_i代替@x = @inputfile.each.count。 wc 非常快,专为此而设计。 -
您能否在运行此脚本时监控 ruby 需要多少 RAM?
-
也许您的系统内存不足,并且在加载足够的行后开始使用页面文件?检查您的进程内存消耗。
-
啊。内存消耗在脚本执行过程中不断增加,直到耗尽所有可用内存并交换启动。减速发生在计算机的 RAM 已满之前,但在填满后会变得更糟。
标签: ruby performance file-io class-method