【发布时间】: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