ruby 中的内存泄漏

Memory leak in ruby

我在 irb 中有这样的代码:

2.6.3 :001 > a = []; 100000000000.times do a.push([1]) end
^CTraceback (most recent call last):
        3: from (irb):1
        2: from (irb):1:in `times'
        1: from (irb):1:in `block in irb_binding'
IRB::Abort (abort then interrupt!)
2.6.3 :002 > a.clear
 => [] 
2.6.3 :003 > GC.start
 => nil 
2.6.3 :004 > a.size
 => 0 
2.6.3 :005 > exit

我的记忆图:

所以只有在出口处内存才完全释放

如何在应用程序退出前完全释放内存?

按设计运行

当且仅当 Ruby 退出后内存没有归还给系统时才是泄漏。由于这不是您所描述的行为,因此可以公平地说您的解释器似乎按设计运行。

请参阅下文,详细了解 Ruby 的垃圾收集如何在较高级别工作,以及为什么您的数组构建如此占用内存。

没有内存泄漏

这不是泄密;这就是 Ruby garbage collection 的工作原理!它基本上是一个标记和清除垃圾收集器,对压缩有一些新的支持。在较高级别,Ruby 为仍在范围内的对象分配内存,并且通常不会释放分配,直到所有引用都超出范围。

Ruby 的垃圾收集在源代码之外没有很好的记录,而且实现比我上面描述的要复杂一些。此外,垃圾收集实现可能因版本而异,并且在不同的解释器(例如 JRuby 和 MRI)之间也是如此!不过,了解您所看到的内容就足够了。

基本上,100000000000.times do a.push([1]) end 会将一个元素推入数组 a 1 亿次。只要 a 在范围内,内存就不会被垃圾回收。即使您在 a 超出范围后手动启动垃圾收集器例程,如果系统没有内存压力,Ruby 可能会或可能不会释放内存。

我不会担心这个,除非你有非常长寿命的进程需要在活动内存中保存数百万条记录。如果这样做,专用缓存或数据库(例如 memcached、Redis)可能会更高效。