Use FnvHashmap for LiveDOMReferences (#37673)

These maps are keyed on pointers, so using FnvHashMap should be faster
and we don't need the collision resistance properties of the default
hasher.

These maps showed up as hot when profiling the testcase from
https://github.com/servo/servo/issues/37223#issuecomment-3000705438.
Switching the hashing algorithm reduces the time spent hashing, but
overall that is still only a fractional part of the testcase.

Testing: Functionality unchanged. Overall the performance change is to
small to show up in any of our automated performance tests. When
comparing the perf profile of the above linked testcase, one should see
a reduction of time spent hashing (inverse call stack)

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
This commit is contained in:
Jonathan Schwender 2025-06-25 08:47:20 +02:00 committed by GitHub
parent ef5784da0d
commit 922d4b83de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 9 additions and 8 deletions

View file

@ -24,12 +24,12 @@
use std::cell::RefCell;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::hash_map::HashMap;
use std::hash::Hash;
use std::marker::PhantomData;
use std::rc::Rc;
use std::sync::{Arc, Weak};
use fnv::FnvHashMap;
use js::jsapi::JSTracer;
use script_bindings::script_runtime::CanGc;
@ -230,8 +230,8 @@ impl<T: DomObject> Clone for Trusted<T> {
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) struct LiveDOMReferences {
// keyed on pointer to Rust DOM object
reflectable_table: RefCell<HashMap<*const libc::c_void, Weak<TrustedReference>>>,
promise_table: RefCell<HashMap<*const Promise, Vec<Rc<Promise>>>>,
reflectable_table: RefCell<FnvHashMap<*const libc::c_void, Weak<TrustedReference>>>,
promise_table: RefCell<FnvHashMap<*const Promise, Vec<Rc<Promise>>>>,
}
impl LiveDOMReferences {
@ -239,8 +239,8 @@ impl LiveDOMReferences {
pub(crate) fn initialize() {
LIVE_REFERENCES.with(|r| {
*r.borrow_mut() = Some(LiveDOMReferences {
reflectable_table: RefCell::new(HashMap::new()),
promise_table: RefCell::new(HashMap::new()),
reflectable_table: RefCell::new(FnvHashMap::default()),
promise_table: RefCell::new(FnvHashMap::default()),
})
});
}
@ -289,7 +289,7 @@ impl LiveDOMReferences {
}
/// Remove null entries from the live references table
fn remove_nulls<K: Eq + Hash + Clone, V>(table: &mut HashMap<K, Weak<V>>) {
fn remove_nulls<K: Eq + Hash + Clone, V>(table: &mut FnvHashMap<K, Weak<V>>) {
let to_remove: Vec<K> = table
.iter()
.filter(|&(_, value)| Weak::upgrade(value).is_none())