-
-
Notifications
You must be signed in to change notification settings - Fork 73
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
expose raw hash APIs #135
Comments
Hi. Thank you for using Moka. It would not be necessary to expose these APIs. You can write your oun hasher, which simply pass-through the pre-calculated hash value. And then you can give the hasher to the cache. Here is an example: use std::{
hash::{BuildHasherDefault, Hash, Hasher},
sync::Arc,
};
//
// Define a struct for the key, which holds the key and its hash value.
//
#[derive(Clone, PartialEq, Eq)]
pub struct MyKey {
_key: Arc<Box<[u8]>>,
hash_value: u64,
}
impl MyKey {
pub fn new(key: Box<[u8]>, hash_value: u64) -> Self {
Self {
_key: Arc::new(key),
hash_value,
}
}
}
// Implement Hash. We will only use the pre-calculated hash value.
impl Hash for MyKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.hash_value.hash(state);
}
}
//
// Create a Hasher, which just uses a single u64 value as the final hash.
//
#[derive(Default)]
struct PassthroughHasher(u64);
impl Hasher for PassthroughHasher {
fn write_u64(&mut self, i: u64) {
self.0 = i;
}
fn write(&mut self, _bytes: &[u8]) {
unimplemented!()
}
fn finish(&self) -> u64 {
self.0
}
}
// Define a BuildHasher using our Hasher. We will give this to our cache.
type PassthroughBuildHasher = BuildHasherDefault<PassthroughHasher>;
fn main() {
let cache = moka::sync::Cache::builder()
.max_capacity(100)
// Give our build hasher to this cache.
.build_with_hasher(PassthroughBuildHasher::default());
let key1 = MyKey::new(b"key1".to_vec().into_boxed_slice(), 0);
let key2 = MyKey::new(b"key2".to_vec().into_boxed_slice(), 1);
cache.insert(key1.clone(), "value1");
cache.insert(key2.clone(), "value2");
assert_eq!(cache.get(&key1), Some("value1"));
assert_eq!(cache.get(&key2), Some("value2"));
} Will this trick work for you? |
it would, but i would think it is perhaps more ergonomic to provide something similar to the raw_entry API from hashbrown https://docs.rs/hashbrown/latest/hashbrown/raw/struct.RawTable.html#method.insert, etc, especially if these functions are already implemented. |
Unfortunately, exposing Like many other hash tables, Moka cache's internal hash table re-calculates hash values of existing keys when it resizes (reallocates) the storage area for growth. This operation is called rehashing. So even though, you use the pre-calculated hash when inserting and retrieving an entry, the cache will still re-calculate hashes from the keys when the cache grows. If you use a different hash function for pre-calculating the hash to the hash function that the cache is given at the build time, it will break; On the other hand, the example code above with |
ah, i missed that. thanks a lot :) |
I have a use case where i want to cache an object which is keyed by a pretty large object that is deserialized. calculating the hash for this key is already done as part of deserializing and parsing,and it would be a substantial performance gain to not have to rehash it. i saw that there are in fact functions that are currently
pub(crate)
such asget_with_hash
orinsert_with_hash
. would it be possible to expose them in the public API?if you dont want those functions completely public for API stability reasons, it would still be nice to expose them behind a feature flag, for those of us who have some specialized use cases :)
The text was updated successfully, but these errors were encountered: