-
Notifications
You must be signed in to change notification settings - Fork 139
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
rebis-dev: Make AtomTable fully safe and prepare for garbage collection #2736
base: rebis-dev
Are you sure you want to change the base?
Conversation
To group all the unsafe blocks of the module close to one another
Thank you a lot, very interesting! One conceptual question I have about this: What exactly is it that makes for example defragmentation possible in this representation, but not the other? It seems that if one is able to do it in one of them, then also on the other (possibly by temporarily building such an index, though with the benefit of avoiding the indirection every time an atom is referenced). |
It's a compromise between performance and safety, mainly. Defragmentation was already possible beforehand, but it required going through the heap to modify any affected The current issue with
I have thought about multiple ways to ensure that that doesn't happen, which fall into two categories:
I personally believe that choosing to make step 3 impossible will lead to code that is harder to reason about, which, given the fuzzy nature of the human mind, can increase the number of bugs that could sneak through. There is a performance penalty to going with step 2, of course. I've measured my method to increase the benchmark times by something between 3% and 5%. |
Thank you a lot, this seems very well thought through! In my opinion, we need unbreakable software, even if it is 10 times slower than other systems. A 5% overhead is completely acceptable. |
This is a followup to #2727 that gives
AtomTable
the ability to verify thatAtom
s are safe to dereference and the ability to shuffle their layout for garbage collection purposes, by adding another layer of indirection.Prior to this change,
Atom
s would contain the offset of theirAtomHeader
within a buffer. This lets us resize the buffer to add new atoms, but it is prone to issues caused by atoms with invalid offsets and it doesn't let us defragment theAtomTable
once garbage collection is introduced.With this change, the
Atom
s now store an index into an array of indices, meaning that verifying the validity of an atom is as simple as checking that it is within this array:This also lets us safely change the order of atoms within the buffer, by changing the offsets, without needing to modify the existing
Atom
s, which paves the way towards garbage collection withinAtomTable
.One important detail with my implementation is that the
offsets
array is stored within anArcu
, which means that the read from the buffer inAtom::as_ptr
now depends onatom_table.inner.offsets.read()
, which is an acquire atomic operation. When a new atom is added to the table withAtomTable::build_with
, the write to the buffer is sequenced beforeatom_table.inner.offsets.replace(new_offsets)
:Atom::as_ptr
is now guaranteed (by my limited experience with atomics) to observe the changes as expected.Instances where the lack of this property cause actual issues are exceedingly rare. A thread would need to somehow have access to an atom offset created from another thread, without synchronization, and immediately try to read its data.
The
Sync
-ness ofAtomTable
is now proved, making it (hopefully) safe :)Please don't be scared by the number of commits and the number of lines changed, they will reduce once #2727 gets merged.