File.realpath()是否会泄漏内存?

时间:2018-08-21 20:06:49

标签: ruby

我在处理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()的调用的版本相同。

1 个答案:

答案 0 :(得分:0)

我使用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对象,然后将其打印到控制台。