Hoy aprendí sobre Ruby Garbage Collection y realicé algunas pruebas.
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 = /[az]/ } # => 1, so only the string `s` be counted count_allocated_objects { s = "this is a string" s.gsub(/[az]/, "") } # => 6, in this case, is the regex `/[az]/` counted ? Como puede ver, parece que el GC no cuenta la expresión regular /[az]/ . ¿Es la regla de Ruby o la regla stat total_allocated_objects de GC?
Resulta que Regex se considera un frozen object (similar a la Cadena congelada) y el GC no contará esos frozen objects , por lo que Regex no se contará. (independientemente de qué versión de Ruby, al menos hasta ahora)
count_allocated_objects { s1 = "this is a string" s2 = "another string" r = /[az]/ } # ruby 2.6.5 => 2, ruby 3.0.0 => 2, ruby 3.1.0 => 3 aunque ruby 3.1.0 devuelve 3, pero si elimino r del código anterior, todavía devuelve 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 => 3prueba con una cadena congelada
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 Seguro que verifiqué un String y Regexp congelados en un heap dump
require 'objspace' ObjectSpace.trace_object_allocations_start s1 = "this is a string" s2 = "another string".freeze r = /[az]/ 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\"