【问题标题】:Does File.realpath() leak memory?File.realpath() 是否泄漏内存?
【发布时间】:2019-01-28 01:44:35
【问题描述】:

我在 File.realpath() 周围留下似乎没有被垃圾收集的字符串时遇到问题。在我看来,这就像内存泄漏,虽然我无法想象这样的事情对于核心库方法实际上是真实的。

考虑以下代码:

def string_test(string)
  puts string
end


GC.start
report = MemoryProfiler.report do
   s = './foo.txt'.freeze
   string_test(s)
   s = nil
   GC.start
end
report.pretty_print

这会产生(以及其他详细输出):

Total allocated: 0 bytes (0 objects)
Total retained:  0 bytes (0 objects)

到目前为止一切顺利,调用 string_test() 方法似乎没有剩余内存使用。但是,如果我更改解析相对路径的方法如下:

def string_test(string)
  puts File.realpath(string)
end

我从 MemoryProfiler 得到以下输出:

Total allocated: 128 bytes (2 objects)
Total retained:  88 bytes (1 objects)
.
.
.
Retained String Report
-----------------------------------
          1  "/home/asdfjk/tmp/foo.txt"
          1  t:28 

foo.txt 是指向实际文件的符号链接。我不知道这是否相关。似乎 File.realpath() 正在留下字符串的副本。将其聚合到数十万个文件中,它会占用大量内存。谁能帮助我了解这里发生了什么以及如何解决它?

另一个有趣的花絮是,在第一个示例中(不泄漏的示例),字符串 s 必须被冻结,否则结果与包含对 File.realpath() 的调用的版本相同。

【问题讨论】:

  • 红宝石版本?
  • ruby 2.5.1p57(2018-03-29 修订版 63029)[x86_64-linux-gnu]
  • 不要分配一个字符串,而是尝试赚一百万,调用GC.start,然后检查。垃圾收集器可能不会做任何事情,因为没有足够的工作要做。

标签: ruby


【解决方案1】:

我使用ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin18] 和文件./foo.txt 进行了测试,这也是一个符号链接./foo

如果我们将您的示例缩减到最低限度,那么答案是否定的,File.realpath 中没有内存泄漏:

require 'memory_profiler'
MemoryProfiler.report { puts File.realpath('./foo.txt') }.pretty_print
<snip>
Retained String Report
-----------------------------------

您看到的问题归结为您对GC.start.freeze 的调用以及MemoryProfiler 在代码块中测量这些内容的方式。

至于为什么puts stringputs File.realpath(string)表现不同,puts string读取string的值并打印到控制台; puts File.realpath(string)创建一个新的String 对象,然后将其打印到控制台。

【讨论】:

  • 抱歉,迟来的回复。谢谢你的澄清。非常感谢
猜你喜欢
  • 2012-09-13
  • 2020-07-22
  • 2010-10-13
  • 2015-02-07
  • 2011-01-29
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
  • 2011-06-26
相关资源
最近更新 更多