From 720b17a54b6abea9a407f80870fba6b9b859c8a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 7 Aug 2017 13:36:34 +0200 Subject: [PATCH] style: Avoid hashing the precomputed hash atoms already have. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This shaves a fair amount of time of stylist rebuild. Most of the extra remaining overhead are memory allocations... I'll try to get those sorted out next, though fixing that may overlap quite a bit with the work Cameron is doing in bug 1382925. MozReview-Commit-ID: 3j2SBY4QnKf Signed-off-by: Emilio Cobos Álvarez --- components/style/lib.rs | 2 +- components/style/selector_map.rs | 51 +++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/components/style/lib.rs b/components/style/lib.rs index e1453706977..fcf48752530 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -71,7 +71,7 @@ extern crate ordered_float; extern crate owning_ref; extern crate parking_lot; extern crate pdqsort; -#[cfg(feature = "gecko")] extern crate precomputed_hash; +extern crate precomputed_hash; extern crate rayon; extern crate selectors; #[cfg(feature = "servo")] #[macro_use] extern crate serde; diff --git a/components/style/selector_map.rs b/components/style/selector_map.rs index c4bc3dcadb0..d4775f315ab 100644 --- a/components/style/selector_map.rs +++ b/components/style/selector_map.rs @@ -9,19 +9,54 @@ use {Atom, LocalName}; use applicable_declarations::ApplicableDeclarationBlock; use context::QuirksMode; use dom::TElement; -use fnv::FnvHashMap; use pdqsort::sort_by; +use precomputed_hash::PrecomputedHash; use rule_tree::CascadeLevel; use selector_parser::SelectorImpl; use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlags}; use selectors::parser::{Component, Combinator, SelectorIter}; use selectors::parser::LocalName as LocalNameSelector; use smallvec::{SmallVec, VecLike}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::collections::hash_map; -use std::hash::Hash; +use std::hash::{BuildHasherDefault, Hash, Hasher}; use stylist::Rule; +/// A hasher implementation that doesn't hash anything, because it expects its +/// input to be a suitable u32 hash. +pub struct PrecomputedHasher { + hash: u32, +} + +impl Default for PrecomputedHasher { + fn default() -> Self { + Self { hash: 0 } + } +} + +/// A simple alias for a hashmap using PrecomputedHasher. +pub type PrecomputedHashMap = HashMap>; + +/// A simple alias for a hashset using PrecomputedHasher. +pub type PrecomputedHashSet = HashSet>; + +impl Hasher for PrecomputedHasher { + #[inline] + fn write(&mut self, _: &[u8]) { + unreachable!() + } + + #[inline] + fn write_u32(&mut self, i: u32) { + self.hash = i; + } + + #[inline] + fn finish(&self) -> u64 { + self.hash as u64 + } +} + /// A trait to abstract over a given selector map entry. pub trait SelectorMapEntry : Sized + Clone { /// Gets the selector we should use to index in the selector map. @@ -63,7 +98,7 @@ pub struct SelectorMap { /// A hash from a class name to rules which contain that class selector. pub class_hash: MaybeCaseInsensitiveHashMap>, /// A hash from local name to rules which contain that local name selector. - pub local_name_hash: FnvHashMap>, + pub local_name_hash: PrecomputedHashMap>, /// Rules that don't have ID, class, or element selectors. pub other: Vec, /// The number of entries in this map. @@ -434,7 +469,7 @@ pub fn get_local_name(iter: SelectorIter) } #[inline] -fn find_push(map: &mut FnvHashMap, +fn find_push(map: &mut PrecomputedHashMap, key: Str, value: V) where VL: VecLike + Default @@ -442,15 +477,15 @@ fn find_push(map: &mut FnvHashMap, map.entry(key).or_insert_with(VL::default).push(value) } -/// Wrapper for FnvHashMap that does ASCII-case-insensitive lookup in quirks mode. +/// Wrapper for PrecomputedHashMap that does ASCII-case-insensitive lookup in quirks mode. #[derive(Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub struct MaybeCaseInsensitiveHashMap(FnvHashMap); +pub struct MaybeCaseInsensitiveHashMap(PrecomputedHashMap); impl MaybeCaseInsensitiveHashMap { /// Empty map pub fn new() -> Self { - MaybeCaseInsensitiveHashMap(FnvHashMap::default()) + MaybeCaseInsensitiveHashMap(PrecomputedHashMap::default()) } /// HashMap::entry