23 Commits

Author SHA1 Message Date
Koichi Sasada
3c3a805c35 mark internal cross-Ractor structures as shareable
The concurrent set, managed id-table dups and symbol id-entry buckets are
reachable from every Ractor via VM-global state (the frozen-string/symbol
tables, shape-tree edge tables, the symbol table), so flag them shareable --
as enc_list_update already does for the encoding list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 23:50:37 +09:00
John Hawthorn
daffaaee73 Mark most TypedData types as THREAD_SAFE_FREE
Set RUBY_TYPED_THREAD_SAFE_FREE on TypedData types whose dfree function
is trivially safe, and only frees its own memory

Types not yet marked as THREAD_SAFE_FREE:
- id2ref_tbl_type: sets the process-global id2ref_tbl to NULL.
- mutex_data_type: unlinks itself from another thread's keeping_mutexes list.
- autoload_data_type: deletes nodes from a shared intrusive list.
- autoload_const_type: deletes itself from a shared list.
- rb_cont_data_type: mutates the shared fiber pool and the global first_jit_cont list.
- rb_fiber_data_type: delegates to cont_free.
- FiberPoolDataType: mutates shared fiber pool free-lists.
- ractor_data_type: reconfigures global VM event-hook flags and call caches.
- exported_object_registry: frees a global table under the VM lock.
- rb_box_data_type (Box::Entry): unlinks classext from other live class and module objects.
- box_ext_cleanup_type: dereferences another String object and calls unlink.
- monitor_data_type: uses the default free, so the flag has no effect.

Co-authored-by: Luke Gruber <luke.gruber@shopify.com>
2026-06-23 13:30:26 -07:00
Luke Gruber
ee90e8e380 Concurrent set fix when encountering garbage obj in find_or_insert
When CASing the garbage key to EMPTY, if we succeed we should decrease
set->size because we're trying to re-insert into the same slot right after.
The insertion increases set->size if it succeeds. This issue can lead to
set->size being overcounted, which can lead to more table resizes.
2026-04-13 19:49:27 -04:00
Jean Boussier
54df6cddd7 concurrent_set.c: Replace ruby_xfree by ruby_sized_xfree 2026-01-31 10:35:48 +01:00
John Hawthorn
375025a386 Fix typo and shadowing 2025-12-09 22:48:06 -08:00
John Hawthorn
462df17f86 Attempt to reuse garbage slots in concurrent hash
This removes all allocations from the find_or_insert loop, which
requires us to start the search over after calling the provided create
function.

In exchange that allows us to assume that all concurrent threads insert
will get the same view of the GC state, and so should all be attempting
to clear and reuse a slot containing a garbage object.
2025-12-09 22:48:06 -08:00
John Hawthorn
81fbdff8fd Use continuation bit in concurrent set
This refactors the concurrent set to examine and reserve a slot via CAS
with the hash, before then doing the same with the key.

This allows us to use an extra bit from the hash as a "continuation bit"
which marks whether we have ever probed past this key while inserting.
When that bit isn't set on deletion we can clear the field instead of
placing a tombstone.
2025-12-09 22:48:06 -08:00
Hiroshi SHIBATA
79c57d747f Fixed by misspell -w -error -source=text 2025-12-09 17:48:57 +09:00
Luke Gruber
2afcdc6902
Change load factor of concur. set from 0.5 to 0.75 (#15007)
Before, the 50% load factor was not working correctly with the new capacity
calculation on resize and too many resizes were seen.

Before this change
------------------

Example:

old_capacity = 32
old_size = 16
deleted_entries = 2 (almost all live)

That means we have:
expected_size = 14
We'll see that 64 > 14 * 4

We'll end up using 32 as the new capacity (same as old) even though that only
leaves us two elements free before we'd have to rebuild again.

Co-authored-by: John Hawthorn <john.hawthorn@shopify.com>
2025-10-30 17:14:36 -04:00
John Hawthorn
45c016866c Use explicit memory orders in concurrent_set
The atomic load/store operations here should mostly be using
release/acquire semantics. This may lead to better performance than what
we had under the default seq_cst.

On x86 this may make the atomic store of hash faster, as it can avoid
xchg. On ARM the loads may be faster (depending on target CPU for the
compiler).

Reference for comparison of atomic operations
https://godbolt.org/z/6EdaMa5rG
2025-10-15 18:21:52 -07:00
John Hawthorn
0a6cd03b3d Add ASSERT_vm_locking_with_barrier
Previously we just had a comment stating that the code required a
barrier. Turns out it's not too difficult to properly assert that.

Co-authored-by: Luke Gruber <luke.gru@gmail.com>
2025-10-10 11:09:34 -07:00
John Hawthorn
399e2abc43 Allow concurrent_set to be collected in minor GC
When testing we've found that the concurrent_set objects used for
fstrings can grow quite large, and because they reach oldgen quickly end
up not being collected.

This commit is a bit of a hack but aims to improve that by moving the
objects to not be WB_PROTECTED. "Unprotected" objects do not age and
can't become oldgen, so this allows them to be collected in a minor GC.
2025-09-10 13:25:24 -07:00
Kunshan Wang
0f408602cb Fix missing increment of deleted_entries
When `rb_concurrent_set_foreach_with_replace` deletes entries from a
concurrent set, it should increment the `deleted_entries` field, too.
2025-07-22 10:05:24 -04:00
Peter Zhu
6b0e5de4e6 Don't rehash on retry in concurrent set
Since the hash should never change, we only need to calculate it once.
2025-07-21 10:58:30 -04:00
Peter Zhu
66349692f0 Introduce free function to rb_concurrent_set_funcs
If we create a key but don't insert it (due to other Ractor winning the
race), then it would leak memory if we don't free it. This introduces a
new function to free that memory for this case.
2025-07-21 10:58:30 -04:00
Peter Zhu
efc232241e Don't call cmp on garbage objects
If the object is garbage, then calling cmp on it may crash.
2025-07-21 10:58:30 -04:00
Peter Zhu
2bcb155b49 Convert global symbol table to concurrent set 2025-07-21 10:58:30 -04:00
Peter Zhu
f05ee26a1f Add rb_concurrent_set_find 2025-07-21 10:58:30 -04:00
Peter Zhu
9ef482bd13 Add rb_concurrent_set_size 2025-07-21 10:58:30 -04:00
Peter Zhu
5d44f2917f Skip garbage check for special consts in concurrent set
rb_objspace_garbage_object_p expects only GC managed objects to be passed
in. We should skip the check if curr_key is a special constant.
2025-07-21 10:58:30 -04:00
Peter Zhu
dafc4e131e Fix size assertion in concurrent set resizing
Since we resize when `prev_size > set->capacity / 2`, it's possible that
`prev_size == set->capacity / 2`, so we need to change the assertion in
concurrent_set_try_resize_without_locking to be
`new_set->size <= new_set->capacity / 2`.
2025-07-18 10:01:06 -04:00
Peter Zhu
f5312d8e7f Make rb_concurrent_set_funcs const
We should never modify rb_concurrent_set_funcs during runtime, so we can
make it const.
2025-07-15 09:55:36 -04:00
Jean Boussier
0bb44f291e Rename ractor_safe_set into concurrent_set
There's nothing ractor related in them, and the classic terminology
for these sort of data structures is `concurrent-*`, e.g.
concurrent hash.
2025-07-07 15:12:39 +02:00