summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <peter@peterzhu.ca>2024-08-15 13:22:39 -0400
committerPeter Zhu <peter@peterzhu.ca>2024-08-16 09:26:51 -0400
commitbbbe07a5dbe9fd747a62c202cfa5d4f2f3cbe52c (patch)
tree379909d59059f2a2fbbf8e134810da65dcf0035d
parent703305bd039804a0fe47e9d5d1f90c9acbdacebd (diff)
Speed up finalizers for objects without object ID
If the object being finalized does not have an object ID, then we don't need to insert into the object ID table, we can simply just allocate a new object ID by bumping the next_object_id counter. This speeds up finalization for objects that don't have an object ID. For example, the following script now runs faster: 1_000_000.times do o = Object.new ObjectSpace.define_finalizer(o) {} end Before: Time (mean ± σ): 1.462 s ± 0.019 s [User: 1.360 s, System: 0.094 s] Range (min … max): 1.441 s … 1.503 s 10 runs After: Time (mean ± σ): 1.199 s ± 0.015 s [User: 1.103 s, System: 0.086 s] Range (min … max): 1.181 s … 1.229 s 10 runs
-rw-r--r--gc/default.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/gc/default.c b/gc/default.c
index 28923a79c7..93f116a276 100644
--- a/gc/default.c
+++ b/gc/default.c
@@ -3046,6 +3046,19 @@ rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj)
}
static VALUE
+get_object_id_in_finalizer(rb_objspace_t *objspace, VALUE obj)
+{
+ if (FL_TEST(obj, FL_SEEN_OBJ_ID)) {
+ return rb_gc_impl_object_id(objspace, obj);
+ }
+ else {
+ VALUE id = ULL2NUM(objspace->next_object_id);
+ objspace->next_object_id += OBJ_ID_INCREMENT;
+ return id;
+ }
+}
+
+static VALUE
get_final(long i, void *data)
{
VALUE table = (VALUE)data;
@@ -3065,7 +3078,7 @@ run_final(rb_objspace_t *objspace, VALUE zombie)
FL_UNSET(zombie, FL_FINALIZE);
st_data_t table;
if (st_delete(finalizer_table, &key, &table)) {
- rb_gc_run_obj_finalizer(rb_gc_impl_object_id(objspace, zombie), RARRAY_LEN(table), get_final, (void *)table);
+ rb_gc_run_obj_finalizer(get_object_id_in_finalizer(objspace, zombie), RARRAY_LEN(table), get_final, (void *)table);
}
else {
rb_bug("FL_FINALIZE flag is set, but finalizers are not found");
@@ -3248,7 +3261,7 @@ rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr)
while (list) {
struct force_finalize_list *curr = list;
- rb_gc_run_obj_finalizer(rb_gc_impl_object_id(objspace, curr->obj), RARRAY_LEN(curr->table), get_final, (void *)curr->table);
+ rb_gc_run_obj_finalizer(get_object_id_in_finalizer(objspace, curr->obj), RARRAY_LEN(curr->table), get_final, (void *)curr->table);
st_data_t obj = (st_data_t)curr->obj;
st_delete(finalizer_table, &obj, 0);