【问题标题】:Memory Management in RubyRuby 中的内存管理
【发布时间】:2016-12-01 04:59:50
【问题描述】:

我对 ruby​​ 的一些行为以及它如何管理内存感到困惑。

我了解 Ruby GC(主要或次要)行为,即如果任何对象计数超过阈值或限制(即 heap_available_slots、old_objects_limit、remembered_shady_object_limit、malloc_limit)。 Ruby 运行/触发 GC(主要或次要)。

如果在 GC 之后找不到足够的内存,Ruby 会为正在运行的程序分配更多内存(我假设基本上是 malloc)。

另外,众所周知,by 确实会立即将内存释放回操作系统。

现在..

我无法理解 Ruby 是如何在不触发任何 GC 的情况下释放内存(返回操作系统)的。

例子

require 'rbtrace'

index = 1
array = []
while(index < 20000000) do 
   array << index
   index += 1
end


sleep 10
print "-"
array=nil
sleep

这是我的例子。如果在 ruby​​ 2.2.2p95 上运行上述代码。 htop显示进程(test.rb PID 11483)的RSS计数达到161MB。

GC.stat(通过rbtracegem截取)长得像(密切关注关注GC count

rbtrace -p 11843 -e '[Time.now,Process.pid,GC.stat]'

[Time.now,Process.pid,GC.stat]
=> [2016-07-27 13:50:28 +0530, 11843, 
{
  "count": 7,
  "heap_allocated_pages": 74,
  "heap_sorted_length": 75,
  "heap_allocatable_pages": 0,
  "heap_available_slots": 30162,
  "heap_live_slots": 11479,
  "heap_free_slots": 18594,
  "heap_final_slots": 89,
  "heap_marked_slots": 120,
  "heap_swept_slots": 18847,
  "heap_eden_pages": 74,
  "heap_tomb_pages": 0,
  "total_allocated_pages": 74,
  "total_freed_pages": 0,
  "total_allocated_objects": 66182,
  "total_freed_objects": 54614,
  "malloc_increase_bytes": 8368,
  "malloc_increase_bytes_limit": 33554432,
  "minor_gc_count": 4,
  "major_gc_count": 3,
  "remembered_wb_unprotected_objects": 0,
  "remembered_wb_unprotected_objects_limit": 278,
  "old_objects": 14,
  "old_objects_limit": 10766,
  "oldmalloc_increase_bytes": 198674592,
  "oldmalloc_increase_bytes_limit": 20132659
}]
*** detached from process 11843

GC count => 7 

大约 25 分钟后。内存已降至 6MB,但 GC 计数仍为 7。

[Time.now,Process.pid,GC.stat]
=> [2016-07-27 14:16:02 +0530, 11843, 
{
  "count": 7,
  "heap_allocated_pages": 74,
  "heap_sorted_length": 75,
  "heap_allocatable_pages": 0,
  "heap_available_slots": 30162,
  "heap_live_slots": 11581,
  "heap_free_slots": 18581,
  "heap_final_slots": 0,
  "heap_marked_slots": 120,
  "heap_swept_slots": 18936,
  "heap_eden_pages": 74,
  "heap_tomb_pages": 0,
  "total_allocated_pages": 74,
  "total_freed_pages": 0,
  "total_allocated_objects": 66284,
  "total_freed_objects": 54703,
  "malloc_increase_bytes": 3248,
  "malloc_increase_bytes_limit": 33554432,
  "minor_gc_count": 4,
  "major_gc_count": 3,
  "remembered_wb_unprotected_objects": 0,
  "remembered_wb_unprotected_objects_limit": 278,
  "old_objects": 14,
  "old_objects_limit": 10766,
  "oldmalloc_increase_bytes": 198663520,
  "oldmalloc_increase_bytes_limit": 20132659
}]

问题:我的印象是每次触发 GC 时 Ruby 都会释放内存。但显然这里不是这样。

任何人都可以提供有关如何(如谁触发内存肯定会释放它的不是 GC)的详细信息。内存被释放回操作系统。

OS: OS X version 10.11.12

【问题讨论】:

    标签: ruby-on-rails ruby garbage-collection


    【解决方案1】:

    你是对的,改变物理内存需求的不是 GC,而是操作系统内核。

    您需要查看VIRT 列,而不是RES 列。如您所见,VIRT 保持不变。

    RES物理(常驻)内存,VIRT 是虚拟(已分配,但当前未使用)内存。

    当进程休眠时,它不会使用其内存或做任何事情,因此操作系统内存管理器决定交换部分物理内存并将其移至虚拟空间。

    为什么要让一个空闲进程无缘无故地占用物理内存?所以操作系统很智能,会尽可能多地换出未使用的物理内存,这就是你看到RES 减少的原因。

    我怀疑即使没有array = nil,只要睡得够久,你也会看到同样的效果。一旦你停止休眠并访问数组中的某些内容,RES 将再次跳回。

    您可以通过这些阅读更多讨论:
    What is RSS and VSZ in Linux memory management
    http://www.darkcoding.net/software/resident-and-virtual-memory-on-linux-a-short-example/
    What's the difference between "virtual memory" and "swap space"?
    http://www.tldp.org/LDP/tlk/mm/memory.html

    【讨论】:

    • 我希望我能阅读更多关于此的任何链接或来源。
    • VIRTUAL 保持不变。另外我如何检查正在使用的虚拟内存电流是多少。我猜是顶部的 SWAP 列具体对吧?
    • 抱歉,我注意到您使用的是 OSX,但它类似于 Linux。在 Linux 上,您可以获得详细的总内存统计信息,例如 cat /proc/meminfo。它不像只看交换那么简单,因为操作系统也使用一些内存来进行磁盘缓存。我添加了一些指向答案的链接,您可以在其中阅读更多内容。
    • 顺便说一句。如果您喜欢非常技术性的文档,那么您可以在这里获得很多详细信息:tldp.org/LDP/tlk/mm/memory.html
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-30
    • 2011-07-25
    • 2012-09-19
    • 2011-01-30
    • 2012-08-27
    相关资源
    最近更新 更多