mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Store the bloom filter in TLS and reuse it across traversals.
MozReview-Commit-ID: EbzDehr2Y2L
This commit is contained in:
parent
d1c31f7eaf
commit
0614010552
2 changed files with 32 additions and 4 deletions
|
@ -31,6 +31,7 @@ use heapsize::HeapSizeOf;
|
||||||
use nodrop::NoDrop;
|
use nodrop::NoDrop;
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use stable_deref_trait::{CloneStableDeref, StableDeref};
|
||||||
use std::{isize, usize};
|
use std::{isize, usize};
|
||||||
use std::borrow;
|
use std::borrow;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
@ -433,6 +434,9 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl<T: ?Sized> StableDeref for Arc<T> {}
|
||||||
|
unsafe impl<T: ?Sized> CloneStableDeref for Arc<T> {}
|
||||||
|
|
||||||
// This is what the HeapSize crate does for regular arc, but is questionably
|
// This is what the HeapSize crate does for regular arc, but is questionably
|
||||||
// sound. See https://github.com/servo/heapsize/issues/37
|
// sound. See https://github.com/servo/heapsize/issues/37
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
|
|
|
@ -7,9 +7,18 @@
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
use atomic_refcell::{AtomicRefMut, AtomicRefCell};
|
||||||
use dom::{SendElement, TElement};
|
use dom::{SendElement, TElement};
|
||||||
|
use owning_ref::OwningHandle;
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
use stylearc::Arc;
|
||||||
|
|
||||||
|
/// Bloom filters are large allocations, so we store them in thread-local storage
|
||||||
|
/// such that they can be reused across style traversals. StyleBloom is responsible
|
||||||
|
/// for ensuring that the bloom filter is zeroed when it is dropped.
|
||||||
|
thread_local!(static BLOOM_KEY: Arc<AtomicRefCell<BloomFilter>> =
|
||||||
|
Arc::new(AtomicRefCell::new(BloomFilter::new())));
|
||||||
|
|
||||||
/// A struct that allows us to fast-reject deep descendant selectors avoiding
|
/// A struct that allows us to fast-reject deep descendant selectors avoiding
|
||||||
/// selector-matching.
|
/// selector-matching.
|
||||||
|
@ -43,8 +52,11 @@ use smallvec::SmallVec;
|
||||||
/// immutable during a restyle.
|
/// immutable during a restyle.
|
||||||
///
|
///
|
||||||
pub struct StyleBloom<E: TElement> {
|
pub struct StyleBloom<E: TElement> {
|
||||||
/// The bloom filter per se.
|
/// A handle to the bloom filter from the thread upon which this StyleBloom
|
||||||
filter: Box<BloomFilter>,
|
/// was created. We use AtomicRefCell so that this is all |Send|, which allows
|
||||||
|
/// StyleBloom to live in ThreadLocalStyleContext, which is dropped from the
|
||||||
|
/// parent thread.
|
||||||
|
filter: OwningHandle<Arc<AtomicRefCell<BloomFilter>>, AtomicRefMut<'static, BloomFilter>>,
|
||||||
|
|
||||||
/// The stack of elements that this bloom filter contains, along with the
|
/// The stack of elements that this bloom filter contains, along with the
|
||||||
/// number of hashes pushed for each element.
|
/// number of hashes pushed for each element.
|
||||||
|
@ -101,11 +113,23 @@ fn each_relevant_element_hash<E, F>(element: E, mut f: F)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: TElement> Drop for StyleBloom<E> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Leave the reusable bloom filter in a zeroed state.
|
||||||
|
self.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<E: TElement> StyleBloom<E> {
|
impl<E: TElement> StyleBloom<E> {
|
||||||
/// Create an empty `StyleBloom`.
|
/// Create an empty `StyleBloom`. Because StyleBloom acquires the thread-
|
||||||
|
/// local filter buffer, creating multiple live StyleBloom instances at
|
||||||
|
/// the same time on the same thread will panic.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
let bloom_arc = BLOOM_KEY.with(|b| b.clone());
|
||||||
|
let filter = OwningHandle::new_with_fn(bloom_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
|
||||||
|
debug_assert!(filter.is_zeroed(), "Forgot to zero the bloom filter last time");
|
||||||
StyleBloom {
|
StyleBloom {
|
||||||
filter: Box::new(BloomFilter::new()),
|
filter: filter,
|
||||||
elements: Default::default(),
|
elements: Default::default(),
|
||||||
pushed_hashes: Default::default(),
|
pushed_hashes: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue