根据我生成字符串的方式,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 并且内存使用调用 GC.start
后实际上会增加到 290MB。
编辑:我正在使用 Ruby 1.9.3-p448,因为我正在处理的项目需要它。虽然我会在 Ruby 2.2 上测试它并返回结果。
编辑 2:在 Ruby 2.1 中运行测试代码(Ruby 2.2 在 RVM 中不可用,我只是想快速运行测试)给出了类似的结果。内存仍然没有降低到合理的状态。它从 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 的非最佳使用。
关于ruby - 为什么 Ruby 只是偶尔释放内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27660966/