Today i learned about Ruby Garbage Collection, and do some test
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 ?
As you can see, it looks like the regex /[a-z]/ is not counted by the GC.
is it the Ruby's rule or the GC's stat total_allocated_objects rule ?
Turn out the Regex is considered as frozen object (similar to the frozen String) and the GC will not count those frozen objects, so the Regex will not be counted. (regardless which Ruby version, at least so far)
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
although ruby 3.1.0 return 3, but if i remove r from the above code, it still return 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
test with a frozen String
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
For sure i checked a frozen String and Regexp in heap dump
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\"