gpt4 book ai didi

ruby - 如何让 Ruby 释放未引用的内存?

转载 作者:IT王子 更新时间:2023-10-28 23:33:43 31 4
gpt4 key购买 nike

考虑这个片段:

l = []

while 1
l << 'a random 369-characterish string'
end
^C
# ran this for maybe 4 seconds, and it had 27 million entries in l. memory
# usage was 1.6 GB.

l = nil

# no change in memory usage

GC.start

# memory usage drops a relatively small amount, from 1.6 GB to 1.39 GB.

我正在将数百万个元素插入/通过 Ruby 的数据结构,并且存在一些严重的内存问题。这个例子表明,即使在没有对现存对象的引用的情况下,Ruby 也不会放过它,即使在显式调用 GC.start 之后也是如此。

我在现实生活中使用的对象总共将数百万个元素插入散列,但散列用作临时查找表,并在某个循环完成后清零。然而,这个查找表中的内存显然永远不会被释放,这会极大地减慢我的应用程序的速度,因为 GC 在每个周期都有数百万个失效对象需要分析。我正在研究 sparsehash gem 的解决方法,但这似乎不是一个棘手的问题,Ruby 运行时应该像这样阻塞。明确删除引用,明确收集和处置对象。谁能帮我弄清楚为什么这没有发生?

我试过 l.delete_if { |x| true} 根据 freenode 上#ruby 中用户的建议,但这确实很慢,而且似乎从未导致明显的内存释放。

使用 ruby 1.9.3p194(2012-04-20 修订版 35410)[x86_64-linux]

编辑:

为了比较,这里是在 python3 中运行的:

l = []

while 1:
l.append('a random 369-characterish string')
^C
# 31,216,082 elements; 246M memory usage.

l = []
# memory usage drops to 8K (0% of system total)

在 python2 上的测试显示几乎相同的结果。

我不确定这是否足以将其视为 MRI 中的实现缺陷,或者它是否只是归因于 GC 的不同方法。无论哪种方式,Python 似乎更适合将总共数百万个元素通过数据结构推送并定期将结构归零的用例(就像临时查找表可能做的那样)。

看起来这确实应该是一个简单的。 :\

最佳答案

有点老套,但您可以尝试将操作fork作为一个单独的进程关闭。该进程将在共享内存空间中运行;当它终止时,内存将被释放。

正如@Sergio Tulentsev 在评论中指出的那样,Ruby 可能不会将内存释放回内核。

此 Ruby/Unix 邮件列表对话对此进行了详细描述:Avoiding system calls

此外,这篇博文将 fork 描述为 Rails 中的内存管理解决方案:Saving memory in Ruby on Rails with fork() and copy-on-write .不过,我认为在 Ruby 2 出来之前,Ruby 不会支持写时复制。

关于ruby - 如何让 Ruby 释放未引用的内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12487986/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com