Project

General

Profile

Actions

Feature #21268

closed

Implement a lock-free hash set for fstring table

Added by jhawthorn (John Hawthorn) 4 days ago. Updated 2 days ago.

Status:
Closed
Target version:
[ruby-core:121670]

Description

I would like to propose replacing the st_table used for fstrings (de-duplicated frozen strings) with a lock-free hash set to have improved performance in a Ractor environment.

Fstrings are shared between Ractors, and can be looked up concurrently by multiple Ractors, it's desirable to be able to do this work in parallel. There should be no change visible to users (other than improved performance :) )

Previously this table used the VM lock (RB_VM_LOCK_ENTER, not the GVL) to serialize access. I first experimented with using a reader-writer lock, but that was a little awkward to use as it was easy to cause a deadlock between the new lock, RB_VM_LOCK_ENTER, and rb_vm_barrier(). An RW lock also can cause cache ping ponging (though striping can help). Lastly, this table is somewhat write-heavy, so it's desirable for even writes to be possible in parallel. A lock free table is not necessarily faster than a table with locking, but due to these constraints and usage I believe a lock-free table is desirable here.

The design is a fairly standard open-addressing hash table with quadratic probing. Similar to our existing st_table or id_table. Deletes (which happen on GC) replace existing keys with a tombstone, which is the only type of update which can occur. Tombstones are only cleared out on rebuilds (necessary for the lock-free design I used).

The set is wait-free for lookup (the thread performing lookup always makes progress) and lock-free for insert (we may sometimes retry if another thread made a concurrent insertion, we never spin on a lock) unless resizing/rebuilding.

The implementation itself is at https://github.com/ruby/ruby/pull/12921 and details are within. I will include benchmarks in a comment below.

Actions

Also available in: Atom PDF

Like1
Like0Like0