add a thread-local cache when using TypeIdMap

This commit is contained in:
Jacob Lifshay 2026-02-01 21:19:32 -08:00
parent e366793204
commit 11281a9842
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
2 changed files with 23 additions and 6 deletions

View file

@ -605,7 +605,14 @@ pub struct Interner<T: ?Sized + 'static + Send + Sync> {
impl<T: ?Sized + 'static + Send + Sync> Interner<T> {
fn get() -> &'static Interner<T> {
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
TYPE_ID_MAP.get_or_insert_default()
thread_local! {
static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() };
}
TYPE_ID_MAP_CACHE.with(|cache| {
cache.get_or_insert_with(|| {
TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default()))
})
})
}
}
@ -1035,10 +1042,17 @@ pub trait MemoizeGeneric: 'static + Send + Sync + Hash + Eq + Copy {
fn inner(self, input: Self::InputRef<'_>) -> Self::Output;
fn get_cow(self, input: Self::InputCow<'_>) -> Self::Output {
static TYPE_ID_MAP: TypeIdMap = TypeIdMap::new();
thread_local! {
static TYPE_ID_MAP_CACHE: TypeIdMap = const { TypeIdMap::new() };
}
let map: &RwLock<(
DefaultBuildHasher,
HashTable<(Self, Self::InputOwned, Self::Output)>,
)> = TYPE_ID_MAP.get_or_insert_default();
)> = TYPE_ID_MAP_CACHE.with(|cache| {
cache.get_or_insert_with(|| {
TYPE_ID_MAP.get_or_insert_with(|| Box::leak(Default::default()))
})
});
fn hash_eq_key<'a, 'b, T: MemoizeGeneric>(
this: &'a T,
input: T::InputRef<'b>,

View file

@ -87,20 +87,23 @@ impl TypeIdMap {
fn insert_slow(
&self,
type_id: TypeId,
make: fn() -> Box<dyn Any + Sync + Send>,
make: impl FnOnce() -> &'static (dyn Any + Sync + Send),
) -> &'static (dyn Any + Sync + Send) {
let value = Box::leak(make());
let value = make();
let mut write_guard = self.0.write().unwrap();
*write_guard.entry(type_id).or_insert(value)
}
pub(crate) fn get_or_insert_default<T: Sized + Any + Send + Sync + Default>(&self) -> &T {
pub(crate) fn get_or_insert_with<T: Sized + Any + Send + Sync>(
&self,
make: impl FnOnce() -> &'static T,
) -> &'static T {
let type_id = TypeId::of::<T>();
let read_guard = self.0.read().unwrap();
let retval = read_guard.get(&type_id).map(|v| *v);
drop(read_guard);
let retval = match retval {
Some(retval) => retval,
None => self.insert_slow(type_id, move || Box::new(T::default())),
None => self.insert_slow(type_id, move || make()),
};
retval.downcast_ref().expect("known to have correct TypeId")
}