如何在 Ruby 中测试 "loop" 与 "while" 没有 GC 的循环内存使用情况

How to test "loop" vs "while" loop memory usage without GC in Ruby

我在 Ruby 版本 2.4 和 2.7 中测试了代码:

1.

    GC.disable

    while true
        ?a
    end

2.

    GC.disable
    puts ?a while true

3.

    GC.disable

    loop do
        ?a
    end

4.

    GC.disable

    loop do
        puts ?a
    end

示例 1 到 4 应该使用所有可用内存和交换,因为它们都在无限循环中创建字符串 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