Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GC API] Change implementation of objects freed at shutdown to use heap walking #87

Open
peterzhu2118 opened this issue Aug 12, 2024 · 1 comment

Comments

@peterzhu2118
Copy link
Collaborator

Right now, we place objects that need to be freed at shutdown into a weak list that is traversed at shutdown. This makes allocation slower and increases memory used.

Allocation:

ruby/gc/mmtk.c

Line 224 in 9903af4

mmtk_add_obj_free_candidate(alloc_obj);

Shutdown:

ruby/gc/mmtk.c

Lines 495 to 503 in 9903af4

struct MMTk_RawVecOfObjRef registered_candidates = mmtk_get_all_obj_free_candidates();
for (size_t i = 0; i < registered_candidates.len; i++) {
VALUE obj = (VALUE)registered_candidates.ptr[i];
if (rb_gc_shutdown_call_finalizer_p(obj)) {
rb_gc_obj_free(objspace_ptr, obj);
}
}
mmtk_free_raw_vec_of_obj_ref(registered_candidates);

Instead, we should use heap walking at shutdown to free these objects.

@wks
Copy link

wks commented Aug 19, 2024

mmtk_add_obj_free_candidate will make allocation slow if the object needs obj_free. But we also need the list of obj_free candidates during normal GC, too, not just during shutdown. During GC, after the liveness of all objects are determined (i.e. after the transitive closure), we go through the list of obj_free candidates to free them. So freeing objects at shutdown using heap walking can't eliminate the need of mmtk_add_obj_free_candidate.

But there is one alternative. We may walk the heap during GC (after transitive closure) to find dying obj_free candidates. Then we don't need mmtk_add_obj_free_candidate at allocation sites. I am not sure if it profitable.

  • The good side is that heap walking goes through memory ranges linearly, and it is cache-friendly. And it can be parallelized. Multiple GC worker threads can walk different blocks.
  • The bad side is that we need to read the header of all objects to know if they are obj_free candidates. And the real bottleneck is free() itself (because it cannot be parallelized, see https://mmtk.zulipchat.com/#narrow/stream/313365-mmtk-ruby/topic/.60free.60.20doesn't.20scale). Meanwhile, we have made efforts so that String, Array and MatchData are no longer obj_free candidates. If only a small fraction of all objects need obj_free, it's better to only register those exceptional objects rather than walking every single object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants