-
Notifications
You must be signed in to change notification settings - Fork 317
feat: HashTable::try_insert_unique_within_capacity
#621
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
base: master
Are you sure you want to change the base?
feat: HashTable::try_insert_unique_within_capacity
#621
Conversation
| /// This does not check if the given element already exists in the table. | ||
| #[cfg_attr(feature = "inline-more", inline)] | ||
| pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> { | ||
| #[inline(always)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used #[inline(always)] unconditionally because this is a helper method which was previously written in line, so I didn't want to worry about abstraction overhead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A simple #[inline] would be sufficient here. We don't want to over-inline in debug builds since this can hurt build times.
| #[cfg_attr(feature = "inline-more", inline)] | ||
| pub fn insert(&mut self, hash: u64, value: T, hasher: impl Fn(&T) -> u64) -> Bucket<T> { | ||
| let slot = match self.find_insert_slot(hash) { | ||
| None => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose someone should check if the unlikely from the new helper find_insert_slot carries over here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use core::hint::cold_path for this (with a wrapper so it works on stable).
src/raw/mod.rs
Outdated
| /// | ||
| /// This does not check if the given element already exists in the table. | ||
| #[inline] | ||
| pub(crate) fn insert_within_capacity(&mut self, hash: u64, value: T) -> Option<Bucket<T>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used pub(crate) because I wasn't sure if we wanted to grow the RawTable API surface at all.
b4184d0 to
639a216
Compare
639a216 to
524982c
Compare
2ce56de to
4188129
Compare
HashTable::insert_unique_within_capacityHashTable::try_insert_unique_within_capacity
This implements #618 with this signature:
This is safe-version from issue feedback, rather than the originally proposed unsafe version.
My personal motivation is to avoid panics. With
HashTable::insert_unique, it callsRawTable::insertwhich callsself.reserve(1, hasher), which will panic out of necessity if allocation fails.Today, you can call
HashTable::try_reservebefore callingHashTable::insert_uniqueto avoid the panic in practice. However, this is not compatible with techniques like usingno-panicto detect at compile/link time that a function does not panic. I have verified with this patch that it'sno_panic::no_paniccompatible. This is not public yet, so I can't share the source for you to verify it yourself, but it's nothing too interesting.This also has an impact on code size. I don't have concrete, trustworthy numbers for this. The compiler does not optimize away the memory growth path in
insert_uniqueafter atry_reserve, so it's easy to see that it should get smaller, it's just a matter of how much.