为什么Ruby有时只释放内存?

时间:2014-12-26 19:13:14

标签: ruby memory-leaks

根据我生成字符串的方式,Ruby会将内存释放到操作系统或者它不会。第一个测试代码将占用大约235MB

size = 2**22
string = '!@#$%^&*()-+~`a1234567890abcdefghijklmnopqrstuvwxyz' * size
puts 'Sleeping...'
sleep(5)
string = nil
GC.start
puts 'Just sitting here..'
gets.chomp

调用GC.start后,测试使用的内存将缩减回几千字节。但是,如果我使用string = (0...size).map { (65 + rand(26)).chr }.join运行相同的测试,则在调用GC.start后,内存将高达250MB,内存使用量实际上会增加到290MB。

编辑:我使用Ruby 1.9.3-p448作为我正在进行的项目需要它。虽然我会在Ruby 2.2上测试它并返回结果。

编辑2:在Ruby 2.1中运行测试代码(Ruby 2.2在RVM中不可用,我只是想快速运行测试)给出了类似的结果。记忆仍然没有降到合理的状态。它从234MB BGC(在GC.start之前)到197MB AGC。注意:内存大小不同,因为我在不同的机器上运行它,但具体的大小不仅仅是相对增加和减少(或非减少)。

1 个答案:

答案 0 :(得分:2)

Ruby MRI不会将内存释放回操作系统。

这是我在OSX 10.10上使用Ruby MRI 2.2看到的,使用典型的ps -o rss

  • 使用*分配大字符串使用~220MB。

  • 使用map分配大字符串使用~340MB。

在我的系统上,GC.start对RSS没有任何作用。换句话说,我看到RAM的使用保持不变。

值得注意的是,map使用了大量的RAM:

  • (0...size).map{ '' }使用~300MB。

当我循环你的例子时,会出现一些有趣的东西:

  • 使用*分配大字符串继续使用相同的RAM,即RSS没有太大变化。

  • 使用map分配大字符串每个循环增加约40M。

  • 只需(0...size).map{ '' }每循环增加约40M。

这告诉我Ruby map可能有与RAM相关的问题。这不是一个问题,因为Ruby没有提出NoMemoryException,但似乎是对RAM的非最佳使用。