summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Zhu <[email protected]>2024-08-14 14:23:26 -0400
committerPeter Zhu <[email protected]>2024-08-21 11:12:07 -0400
commite15b454bc3da5280923325df660f9b05fa34061c (patch)
tree506f9d53163b944a5e896893e39500a494e08968
parent669d1f79d800d554918c7d5647b73a6431920ea8 (diff)
Simplify how finalizers are ran at shutdown
We don't need to build a linked list from the finalizer table and instead we can just run the finalizers by iterating the ST table. This also improves the performance at shutdown, for example: 1_000_000.times.map do o = Object.new ObjectSpace.define_finalizer(o, proc { }) o end Before: Time (mean ± σ): 1.722 s ± 0.056 s [User: 1.597 s, System: 0.113 s] Range (min … max): 1.676 s … 1.863 s 10 runs After: Time (mean ± σ): 1.538 s ± 0.025 s [User: 1.437 s, System: 0.093 s] Range (min … max): 1.510 s … 1.586 s 10 runs
-rw-r--r--gc/default.c51
1 files changed, 18 insertions, 33 deletions
diff --git a/gc/default.c b/gc/default.c
index cf0d9b882a..82794ca6c0 100644
--- a/gc/default.c
+++ b/gc/default.c
@@ -3195,24 +3195,6 @@ gc_abort(void *objspace_ptr)
gc_mode_set(objspace, gc_mode_none);
}
-struct force_finalize_list {
- VALUE obj;
- VALUE table;
- struct force_finalize_list *next;
-};
-
-static int
-force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
-{
- struct force_finalize_list **prev = (struct force_finalize_list **)arg;
- struct force_finalize_list *curr = ALLOC(struct force_finalize_list);
- curr->obj = key;
- curr->table = val;
- curr->next = *prev;
- *prev = curr;
- return ST_CONTINUE;
-}
-
void
rb_gc_impl_shutdown_free_objects(void *objspace_ptr)
{
@@ -3235,6 +3217,23 @@ rb_gc_impl_shutdown_free_objects(void *objspace_ptr)
}
}
+static int
+rb_gc_impl_shutdown_call_finalizer_i(st_data_t key, st_data_t val, st_data_t data)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+ VALUE obj = (VALUE)key;
+ VALUE table = (VALUE)val;
+
+ GC_ASSERT(RB_FL_TEST(obj, FL_FINALIZE));
+ GC_ASSERT(RB_BUILTIN_TYPE(val) == T_ARRAY);
+
+ rb_gc_run_obj_finalizer(rb_gc_impl_object_id(objspace, obj), RARRAY_LEN(table), get_final, (void *)table);
+
+ FL_UNSET(obj, FL_FINALIZE);
+
+ return ST_DELETE;
+}
+
void
rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr)
{
@@ -3254,22 +3253,8 @@ rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr)
return;
}
- /* force to run finalizer */
while (finalizer_table->num_entries) {
- struct force_finalize_list *list = 0;
- st_foreach(finalizer_table, force_chain_object, (st_data_t)&list);
- while (list) {
- struct force_finalize_list *curr = list;
-
- 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);
- FL_UNSET(curr->obj, FL_FINALIZE);
-
- list = curr->next;
- xfree(curr);
- }
+ st_foreach(finalizer_table, rb_gc_impl_shutdown_call_finalizer_i, (st_data_t)objspace);
}
/* run finalizers */