Skip to content

Buffer obj_free candidates.#71

Open
eightbitraptor wants to merge 5 commits intomainfrom
mvh-batch-obj-free-candidates
Open

Buffer obj_free candidates.#71
eightbitraptor wants to merge 5 commits intomainfrom
mvh-batch-obj-free-candidates

Conversation

@eightbitraptor
Copy link
Contributor

@eightbitraptor eightbitraptor commented Feb 12, 2026

Previously, every object allocation in rb_gc_impl_new_obj made a per-object FFI call into Rust (mmtk_add_obj_free_candidate), which acquired a mutex on one of the WeakProcessor's candidate vecs, pushed a single element, and released the mutex. That's an FFI crossing + mutex lock/unlock on every single allocation.

Now, each MMTk_ractor_cache has two local buffers (parallel-freeable and non-parallel-freeable, 128 entries each). On allocation, we just store the pointer into the local buffer. When a buffer fills up, we flush the entire batch in one FFI call using mmtk_add_obj_free_candidates, which does a single mutex acquisition and flushes the batch into the work buckets. The objects are still distributed in teh same way, but now we only take a lock once per queue buffer, rather than per-object.

We picked 128 as our buffer size at random. We should probably investigate further what an optimum size for this is

Previously, every object allocation in rb_gc_impl_new_obj made a
per-object FFI call into Rust (mmtk_add_obj_free_candidate), which
acquired a mutex on one of the WeakProcessor's candidate vecs, pushed a
single element, and released the mutex. That's an FFI crossing + mutex
lock/unlock on every single allocation.

Now, each MMTk_ractor_cache has two local buffers (parallel-freeable and
non-parallel-freeable, 128 entries each). On allocation, we just store
the pointer into the local buffer. When a buffer fills up, we flush the
entire batch in one FFI call using mmtk_add_obj_free_candidates, which
does a single mutex acquisition and extend_from_slice for the whole
batch.

We picked 128 as our buffer size at random. We should probably
investigate further what an optimum size for this is
@eightbitraptor eightbitraptor force-pushed the mvh-batch-obj-free-candidates branch from e444c58 to 23c4a9a Compare February 12, 2026 15:30
shutdown_call_finalizer reads candidates from the Rust-side
WeakProcessor, but the main ractor's C-side buffer may not
have been flushed yet (ractor_cache_free runs later). Flush
all remaining buffers before reading candidates.
Instead of sending all 128 buffered objects to one bucket,
round-robin distribute them across all worker buckets so
parallel obj_free work stays balanced.
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

Successfully merging this pull request may close these issues.

1 participant