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

根据我如何生成字符串,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运行相同的测试,内存将高达250MB,内存使用实际上将增加到290MB GC.start

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

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

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的非最佳使用。