我在 Ruby 版本 2.4 和 2.7 中测试了代码:
1.
GC.disable
while true
?a
end
阿拉伯数字。
GC.disable
puts ?a while true
3.
GC.disable
loop do
?a
end
4.
GC.disable
loop do
puts ?a
end
示例 1 到 4 应使用所有可用内存和交换,因为它们都在无限循环中创建字符串a
,例如:
- GC 已禁用。
- 字符串
a
未冻结。
但是 #1 在执行时消耗的内存不会超过一个字节。 #2、#3 和 #4 使用尽可能多的内存。在我的系统上,它们每秒消耗大约 250 MB 左右。正如预期的那样,CPU 内核的使用率为 100%。
为什么 #1 几乎不消耗任何内存,而其他内存在很短的时间内使用所有可用的系统内存?
> Stefan在他的评论中是正确的,因为while循环不会创建一个新的范围。
还要注意puts
方法的效果。每次为字符串调用它时,它都会在内存中分配一个新对象。
require "benchmark/memory"
Benchmark.memory do |x|
x.report("Test1") { puts ?a }
x.report("Test2") { ?a }
x.report("Test3") { puts ?a; puts ?a; puts ?a; puts ?a; puts ?a; puts ?a; puts ?a; puts ?a; puts ?a; puts ?a }
x.report("Test4") { ?a; ?a; ?a; ?a; ?a; ?a; ?a; ?a; ?a; ?a; }
x.compare!
end
输出:
Calculating -------------------------------------
Test1 40.000 memsize ( 0.000 retained)
1.000 objects ( 0.000 retained)
1.000 strings ( 0.000 retained)
Test2 40.000 memsize ( 0.000 retained)
1.000 objects ( 0.000 retained)
1.000 strings ( 0.000 retained)
Test3 400.000 memsize ( 0.000 retained)
10.000 objects ( 0.000 retained)
1.000 strings ( 0.000 retained)
Test4 40.000 memsize ( 0.000 retained)
1.000 objects ( 0.000 retained)
1.000 strings ( 0.000 retained)
Comparison:
Test1: 40 allocated
Test2: 40 allocated - same
Test3: 400 allocated - 10.00x more
Test4: 40 allocated - same