Ruby GC计数如何分配RegularExpression



今天我学习了Ruby垃圾回收,并做了一些测试

def count_allocated_objects
before = GC.stat(:total_allocated_objects)
yield
after = GC.stat(:total_allocated_objects)
after - before
end
count_allocated_objects {
s = "this is a string"
r = /[a-z]/
} # => 1, so only the string `s` be counted
count_allocated_objects {
s = "this is a string"
s.gsub(/[a-z]/, "")
} # => 6, in this case, is the regex `/[a-z]/` counted ?

正如您所看到的,正则表达式/[a-z]/似乎没有被GC计数。是Ruby的规则还是GC的stattotal_allocated_objects规则?

原来Regex被认为是frozen object(类似于冻结的String(,GC不会计算那些frozen objects,所以Regex不会被计算在内。(不管哪种Ruby版本,至少到目前为止(

count_allocated_objects {
s1 = "this is a string"
s2 = "another string"
r = /[a-z]/
} # ruby 2.6.5 => 2, ruby 3.0.0 => 2, ruby 3.1.0 => 3

虽然ruby 3.1.0返回3,但如果我从上面的代码中删除r,它仍然返回3

count_allocated_objects {
s1 = "this is a string"
s2 = "another string"
} # ruby 2.6.5 => 2, ruby 3.0.0 => 2, ruby 3.1.0 => 3

使用冻结字符串进行测试

count_allocated_objects {
s1 = "this is a string"
s2 = "another string".freeze
} # ruby 2.6.5 => 1, ruby 3.0.0 => 1, ruby 3.1.0 => 2

当然,我在heap dump中检查了一个冻结的String和Regexp

require 'objspace'
ObjectSpace.trace_object_allocations_start
s1 = "this is a string"
s2 = "another string".freeze
r = /[a-z]/
p r.frozen? # true
p ObjectSpace.dump(r) # "{.."type":"REGEXP", ... "frozen":true ...
p ObjectSpace.dump(s2) # "{.."type":"STRING", ... "frozen":true ...
p ObjectSpace.dump(s1) # didn't contain "frozen"

最新更新