ruby - 为什么我的 Ruby 脚本会随着时间的推移变慢?

标签 ruby performance file-io class-method

我有一个 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 脚本中都看到了它,无论是在这台计算机上还是在其他计算机上。

最佳答案

我建议在 DBM 中执行此操作,而不是 Ruby 或任何其他语言。 DBM 可以非常快速地告诉您字段的唯一值,尤其是当它已经被索引时。

尝试用任何语言来做到这一点都是在为通用计算设计的东西中复制数据库的基本功能。

相反,将 Ruby 与 ORM(如 Sequel 或 Active Record)一起使用,并向数据库发出查询并让它返回您想知道的内容。不要遍历每一行,那太疯狂了,要求它为您提供独特的值(value)并从那里开始。

我不会责怪 Ruby,因为在给定相同主机和 RAM 的情况下,任何其他语言都会出现同样的问题。 C/C++ 可能会通过生成更紧凑的代码来延迟不可避免的事情,但是您的开发时间会大大减慢,尤其是当您学习 C 等未知语言时。意外错误的风险会增加,因为您必须做更多的内务管理和防御工作编程比你在 Ruby、Python 或 Perl 中做的要好。

将每个工具用于其设计目的,您将取得领先。

查看您的代码,您可能可以通过不尝试将每一行都保留在内存中来提高通过完整运行的机会。你说你试图确定唯一性,所以只保留你感兴趣的唯一列值,你可以使用 Ruby 的 Set 类轻松地做到这一点。您可以将要确定唯一性的每个事物的值放在上面,遍历文件,Set 将只保留唯一值。

关于ruby - 为什么我的 Ruby 脚本会随着时间的推移变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18795325/

相关文章:

ruby - ruby 中类似界面的设计模式

ruby - 用值初始化数组 (Ruby)

python - 在 Python 中每小时将时间戳写入文件

asp.net - IIS 和 ASP.NET 的耗时差异

matlab - 来自 matlab 的制表符分隔文本文件

javascript - 是否存在用于批处理的免费 JavaScript/ActionScript 解释器?

ruby-on-rails - Google Calendar API V3 - 插入日历

ruby-on-rails - OS X Yosemite 的 Ruby 错误

C# 性能 - 线性数组访问与随机访问

ajax - AJAX 与 Web Sockets 的往返时间