Cache font style struct addresses in a separate font group cache.

On http://en.wikipedia.org/wiki/Spotted_hyena, I was seeing a 100% miss
rate in the first fast cache lookup and 45% of total layout time in this
function. After making this change, the first cache lookup almost always
succeeds, and the time spent in this function drops to 8%.
This commit is contained in:
Patrick Walton 2015-12-11 15:40:21 -05:00
parent d6708a2fea
commit b31a3b3883

View file

@ -82,6 +82,8 @@ pub struct FontContext {
/// per frame. TODO: Make this weak when incremental redraw is done. /// per frame. TODO: Make this weak when incremental redraw is done.
paint_font_cache: Vec<PaintFontCacheEntry>, paint_font_cache: Vec<PaintFontCacheEntry>,
layout_font_group_address_cache: HashMap<usize, Rc<FontGroup>, DefaultState<FnvHasher>>,
layout_font_group_cache: layout_font_group_cache:
HashMap<LayoutFontGroupCacheKey, Rc<FontGroup>, DefaultState<FnvHasher>>, HashMap<LayoutFontGroupCacheKey, Rc<FontGroup>, DefaultState<FnvHasher>>,
@ -97,6 +99,7 @@ impl FontContext {
layout_font_cache: vec!(), layout_font_cache: vec!(),
fallback_font_cache: vec!(), fallback_font_cache: vec!(),
paint_font_cache: vec!(), paint_font_cache: vec!(),
layout_font_group_address_cache: HashMap::with_hash_state(Default::default()),
layout_font_group_cache: HashMap::with_hash_state(Default::default()), layout_font_group_cache: HashMap::with_hash_state(Default::default()),
epoch: 0, epoch: 0,
} }
@ -144,6 +147,7 @@ impl FontContext {
self.layout_font_cache.clear(); self.layout_font_cache.clear();
self.fallback_font_cache.clear(); self.fallback_font_cache.clear();
self.paint_font_cache.clear(); self.paint_font_cache.clear();
self.layout_font_group_address_cache.clear();
self.layout_font_group_cache.clear(); self.layout_font_group_cache.clear();
self.epoch = current_epoch self.epoch = current_epoch
} }
@ -156,17 +160,17 @@ impl FontContext {
self.expire_font_caches_if_necessary(); self.expire_font_caches_if_necessary();
let address = &*style as *const SpecifiedFontStyle as usize; let address = &*style as *const SpecifiedFontStyle as usize;
if let Some(ref cached_font_group) = self.layout_font_group_cache.get(&address) { if let Some(ref cached_font_group) = self.layout_font_group_address_cache.get(&address) {
return (*cached_font_group).clone() return (*cached_font_group).clone()
} }
let layout_font_group_cache_key = LayoutFontGroupCacheKey { let layout_font_group_cache_key = LayoutFontGroupCacheKey {
pointer: style.clone(), pointer: style.clone(),
size: style.font_size, size: style.font_size,
address: address,
}; };
if let Some(ref cached_font_group) = self.layout_font_group_cache.get( if let Some(ref cached_font_group) = self.layout_font_group_cache.get(
&layout_font_group_cache_key) { &layout_font_group_cache_key) {
self.layout_font_group_address_cache.insert(address, (*cached_font_group).clone());
return (*cached_font_group).clone() return (*cached_font_group).clone()
} }
@ -275,6 +279,7 @@ impl FontContext {
let font_group = Rc::new(FontGroup::new(fonts)); let font_group = Rc::new(FontGroup::new(fonts));
self.layout_font_group_cache.insert(layout_font_group_cache_key, font_group.clone()); self.layout_font_group_cache.insert(layout_font_group_cache_key, font_group.clone());
self.layout_font_group_address_cache.insert(address, font_group.clone());
font_group font_group
} }
@ -316,7 +321,6 @@ impl HeapSizeOf for FontContext {
struct LayoutFontGroupCacheKey { struct LayoutFontGroupCacheKey {
pointer: Arc<SpecifiedFontStyle>, pointer: Arc<SpecifiedFontStyle>,
size: Au, size: Au,
address: usize,
} }
impl PartialEq for LayoutFontGroupCacheKey { impl PartialEq for LayoutFontGroupCacheKey {
@ -333,12 +337,6 @@ impl Hash for LayoutFontGroupCacheKey {
} }
} }
impl borrow::Borrow<usize> for LayoutFontGroupCacheKey {
fn borrow(&self) -> &usize {
&self.address
}
}
#[inline] #[inline]
pub fn invalidate_font_caches() { pub fn invalidate_font_caches() {
FONT_CACHE_EPOCH.fetch_add(1, Ordering::SeqCst); FONT_CACHE_EPOCH.fetch_add(1, Ordering::SeqCst);