Rework StringKey to be able to re-use strings for a lower memory footprint.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
By caching strings we make sure we're using the exact same string everywhere, and creating 100 StringKeys of for example `charmander` will use the exact same memory footprint as creating only one.
This commit is contained in:
parent
2aadab5a42
commit
55380f631f
|
@ -1,5 +1,6 @@
|
||||||
|
use hashbrown::HashMap;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex, Weak};
|
||||||
|
|
||||||
/// StringKey is an immutable string that is used for indexing of hashmaps or equality a lot.
|
/// StringKey is an immutable string that is used for indexing of hashmaps or equality a lot.
|
||||||
/// By reference counting the string instead of copying, and caching the hash, we can get some
|
/// By reference counting the string instead of copying, and caching the hash, we can get some
|
||||||
|
@ -11,6 +12,10 @@ pub struct StringKey {
|
||||||
hash: u32,
|
hash: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
static ref STRING_CACHE: Mutex<HashMap<u32, Weak<String>>> = Mutex::new(HashMap::new());
|
||||||
|
}
|
||||||
|
|
||||||
impl StringKey {
|
impl StringKey {
|
||||||
pub const fn get_hash_const<const N: usize>(s: &[u8; N]) -> u32 {
|
pub const fn get_hash_const<const N: usize>(s: &[u8; N]) -> u32 {
|
||||||
let mut crc: u32 = 0xffffffff;
|
let mut crc: u32 = 0xffffffff;
|
||||||
|
@ -33,10 +38,22 @@ impl StringKey {
|
||||||
|
|
||||||
pub fn new(s: &str) -> Self {
|
pub fn new(s: &str) -> Self {
|
||||||
let hash = StringKey::get_hash(s);
|
let hash = StringKey::get_hash(s);
|
||||||
Self {
|
let mut cache = STRING_CACHE.lock().unwrap();
|
||||||
|
let cached_value = cache.get(&hash);
|
||||||
|
if let Some(cached_value) = cached_value {
|
||||||
|
if let Some(cached_value) = cached_value.upgrade() {
|
||||||
|
return Self {
|
||||||
|
str: cached_value,
|
||||||
|
hash,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let v = Self {
|
||||||
str: Arc::new(s.to_string()),
|
str: Arc::new(s.to_string()),
|
||||||
hash,
|
hash,
|
||||||
}
|
};
|
||||||
|
cache.insert(hash, Arc::downgrade(&v.str));
|
||||||
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str(&self) -> &str {
|
pub fn str(&self) -> &str {
|
||||||
|
|
Loading…
Reference in New Issue