【问题标题】:How to avoid memory leaks in Ruby如何避免 Ruby 中的内存泄漏
【发布时间】:2016-11-26 07:25:36
【问题描述】:

我注意到有时我的 ruby​​ 脚本在处​​理小数据时运行得相当好,因为当你给它们一个大数据集来处理时,没有更多的内存了。例如,我有一个很长的脚本,每分钟它都会增加 100 兆字节左右的内存使用量,直到我给它足够大的数据来处理它时它就会崩溃。

那么,问题是,如何避免 ruby​​ 中的内存泄漏,该做什么和不该做什么?有任何提示和技巧可以优化长时间运行脚本的 ruby​​ 内存使用吗?

如何确保我的 ruby​​ 脚本没有泄漏任何内存?

谢谢!

【问题讨论】:

  • 如果不知道正在运行的脚本以及该脚本的输入,很难回答这个问题。
  • 快速破解:不时戳戳GC.start,然后清理您创建的任何垃圾。 Ruby 不会泄漏内存,但您可以创建难以清理的结构,或者您可能会保留对不需要的东西的引用。由于您发布了零代码,我无法真正告诉您您正在处理哪种情况。
  • 值得注意的是,新版本的 Ruby(例如 2.3+)在处理内存清理方面明显优于旧版本,所以如果您没有运行 2.3,请在浪费时间之前尝试升级一个非问题。
  • @tadman - 谢谢,GC.start 帮助了。当您说“您可以创建难以清理的结构,或者您可能保留对您不需要的东西的引用”时,您能举一个简单的例子吗?

标签: ruby memory-management


【解决方案1】:

内存问题的快速修复通常是调用GC.start,这会强制启动垃圾收集器。有时 Ruby 会非常懒惰地清理垃圾,而且垃圾会累积到危险的程度。

有时您会无意中创建难以清理的结构,即那些相互关联的事物,在更深入地分析时,实际上并没有保留下来。这使垃圾收集器的生活变得更加困难。例如,包含大量字符串的深度 Hash 结构比简单的 Array 需要更多的工作来解放。

如果您遇到内存问题,则需要注意在执行操作时产生了多少垃圾。寻找折叠东西以去除中间产品的方法。例如,经典案例是这样的:

s = ''

10.times do |i|
  s += i.to_s
end

这会创建一个01234... 形式的字符串作为最终产品,但它还会创建其他10 个带有中间产品的字符串。这是此解决方案的 11 倍垃圾:

s = ''
10.times do |i|
  s << i.to_s
end

这会创建一个字符串并重复附加到它。从技术上讲,数字上的to_s 操作也会产生垃圾,所以这也是要记住的另一件事,转换不是免费的。这就是为什么你会在 Ruby 中经常看到像 :name 这样的符号,你只需支付一次且一次的成本。每个字符串"name" 都可以是一个独立的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    • 2015-08-27
    • 2018-04-08
    • 2013-06-24
    相关资源
    最近更新 更多