Auto merge of #19512 - mbrubeck:uluru, r=emilio

Improve LRU cache behavior in SelectorFlagsMap

This code used to insert duplicate entries to avoid expensive shuffling of the LRU cache.  With uluru this is no longer necessary, because reordering the cache is cheap.

Now it uses the `LRUCache::find` method from uluru 0.2 to update entries in-place.  This should increase cache hits by eliminating unnecessary evictions.

This PR also updates `arrayvec` because `uluru` depends on it, and `immeta` because it depends on `arrayvec`.

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes do not require tests because they don't change behavior

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19512)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-12-07 16:02:44 -06:00 committed by GitHub
commit 0c13f14aaa
7 changed files with 29 additions and 43 deletions

View file

@ -20,17 +20,13 @@ gecko = ["nsstring", "num_cpus",
"style_traits/gecko", "fallible/known_system_malloc"]
use_bindgen = ["bindgen", "regex", "toml"]
servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5ever",
"cssparser/serde", "encoding_rs", "malloc_size_of/servo",
# FIXME: Uncomment when https://github.com/servo/servo/pull/16953 has landed:
#"arrayvec/use_union"
"cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union",
"servo_url"]
gecko_debug = ["nsstring/gecko_debug"]
[dependencies]
app_units = "0.5.5"
arrayvec = "0.3.20"
arrayvec = "0.4.6"
atomic_refcell = "0.1"
bitflags = "1.0"
byteorder = "1.0"
@ -69,7 +65,7 @@ style_derive = {path = "../style_derive"}
style_traits = {path = "../style_traits"}
servo_url = {path = "../url", optional = true}
time = "0.1"
uluru = "0.1"
uluru = "0.2"
unicode-bidi = "0.3"
unicode-segmentation = "1.0"

View file

@ -515,7 +515,7 @@ pub struct SelectorFlagsMap<E: TElement> {
map: FnvHashMap<SendElement<E>, ElementSelectorFlags>,
/// An LRU cache to avoid hashmap lookups, which can be slow if the map
/// gets big.
cache: LRUCache<CacheItem<E>, [Entry<CacheItem<E>>; 4 + 1]>,
cache: LRUCache<[Entry<CacheItem<E>>; 4 + 1]>,
}
#[cfg(debug_assertions)]
@ -538,17 +538,17 @@ impl<E: TElement> SelectorFlagsMap<E> {
pub fn insert_flags(&mut self, element: E, flags: ElementSelectorFlags) {
let el = unsafe { SendElement::new(element) };
// Check the cache. If the flags have already been noted, we're done.
if self.cache.iter().find(|&(_, ref x)| x.0 == el)
.map_or(ElementSelectorFlags::empty(), |(_, x)| x.1)
.contains(flags) {
if let Some(item) = self.cache.find(|x| x.0 == el) {
if !item.1.contains(flags) {
item.1.insert(flags);
self.map.get_mut(&el).unwrap().insert(flags);
}
return;
}
let f = self.map.entry(el).or_insert(ElementSelectorFlags::empty());
*f |= flags;
// Insert into the cache. We don't worry about duplicate entries,
// which lets us avoid reshuffling.
self.cache.insert((unsafe { SendElement::new(element) }, *f))
}

View file

@ -1809,8 +1809,8 @@ impl SourcePropertyDeclaration {
}
fn push(&mut self, declaration: PropertyDeclaration) {
let over_capacity = self.declarations.push(declaration).is_some();
debug_assert!(!over_capacity);
let _result = self.declarations.try_push(declaration);
debug_assert!(_result.is_ok());
}
}

View file

@ -421,7 +421,7 @@ impl<E: TElement> StyleSharingTarget<E> {
}
struct SharingCacheBase<Candidate> {
entries: LRUCache<Candidate, [Entry<Candidate>; SHARING_CACHE_BACKING_STORE_SIZE]>,
entries: LRUCache<[Entry<Candidate>; SHARING_CACHE_BACKING_STORE_SIZE]>,
}
impl<Candidate> Default for SharingCacheBase<Candidate> {