aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/bloom.rs
diff options
context:
space:
mode:
authorBobby Holley <bobbyholley@gmail.com>2017-06-21 16:56:59 -0700
committerBobby Holley <bobbyholley@gmail.com>2017-06-21 19:53:16 -0700
commit71e76a054d20221e9782cebb12091a81a48fcf4c (patch)
treeae9bbf99abe71a82590606e78d838cd0a02c7a04 /components/style/bloom.rs
parent28c35ac9dfb3063ba7e38514d1bf4ce8b0196dcb (diff)
downloadservo-71e76a054d20221e9782cebb12091a81a48fcf4c.tar.gz
servo-71e76a054d20221e9782cebb12091a81a48fcf4c.zip
Be smarter when clearing the bloom filter.
Diffstat (limited to 'components/style/bloom.rs')
-rw-r--r--components/style/bloom.rs21
1 files changed, 20 insertions, 1 deletions
diff --git a/components/style/bloom.rs b/components/style/bloom.rs
index 5033ff6ce83..34b6b608962 100644
--- a/components/style/bloom.rs
+++ b/components/style/bloom.rs
@@ -54,6 +54,16 @@ pub struct StyleBloom<E: TElement> {
pushed_hashes: SmallVec<[u32; 64]>,
}
+/// The very rough benchmarks in the selectors crate show clear()
+/// costing about 25 times more than remove_hash(). We use this to implement
+/// clear() more efficiently when only a small number of hashes have been
+/// pushed.
+///
+/// One subtly to note is that remove_hash() will not touch the value
+/// if the filter overflowed. However, overflow can only occur if we
+/// get 255 collisions on the same hash value, and 25 < 255.
+const MEMSET_CLEAR_THRESHOLD: usize = 25;
+
struct PushedElement<E: TElement> {
/// The element that was pushed.
element: SendElement<E>,
@@ -166,8 +176,17 @@ impl<E: TElement> StyleBloom<E> {
/// Clears the bloom filter.
pub fn clear(&mut self) {
- self.filter.clear();
self.elements.clear();
+
+ if self.pushed_hashes.len() > MEMSET_CLEAR_THRESHOLD {
+ self.filter.clear();
+ self.pushed_hashes.clear();
+ } else {
+ for hash in self.pushed_hashes.drain() {
+ self.filter.remove_hash(hash);
+ }
+ debug_assert!(self.filter.is_zeroed());
+ }
}
/// Rebuilds the bloom filter up to the parent of the given element.