diff options
author | Peter Zhu <[email protected]> | 2024-08-14 14:23:26 -0400 |
---|---|---|
committer | Peter Zhu <[email protected]> | 2024-08-21 11:12:07 -0400 |
commit | e15b454bc3da5280923325df660f9b05fa34061c (patch) | |
tree | 506f9d53163b944a5e896893e39500a494e08968 | |
parent | 669d1f79d800d554918c7d5647b73a6431920ea8 (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.c | 51 |
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 */ |