今天我学习了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"