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.
paint_font_cache: Vec<PaintFontCacheEntry>,
layout_font_group_address_cache: HashMap<usize, Rc<FontGroup>, DefaultState<FnvHasher>>,
layout_font_group_cache:
HashMap<LayoutFontGroupCacheKey, Rc<FontGroup>, DefaultState<FnvHasher>>,
@ -97,6 +99,7 @@ impl FontContext {
layout_font_cache: vec!(),
fallback_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()),
epoch: 0,
}
@ -144,6 +147,7 @@ impl FontContext {
self.layout_font_cache.clear();
self.fallback_font_cache.clear();
self.paint_font_cache.clear();
self.layout_font_group_address_cache.clear();
self.layout_font_group_cache.clear();
self.epoch = current_epoch
}
@ -152,21 +156,21 @@ impl FontContext {
/// a cached font if this font instance has already been used by
/// this context.
pub fn layout_font_group_for_style(&mut self, style: Arc<SpecifiedFontStyle>)
-> Rc<FontGroup> {
-> Rc<FontGroup> {
self.expire_font_caches_if_necessary();
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()
}
let layout_font_group_cache_key = LayoutFontGroupCacheKey {
pointer: style.clone(),
size: style.font_size,
address: address,
};
if let Some(ref cached_font_group) = self.layout_font_group_cache.get(
&layout_font_group_cache_key) {
self.layout_font_group_address_cache.insert(address, (*cached_font_group).clone());
return (*cached_font_group).clone()
}
@ -275,6 +279,7 @@ impl FontContext {
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_address_cache.insert(address, font_group.clone());
font_group
}
@ -316,7 +321,6 @@ impl HeapSizeOf for FontContext {
struct LayoutFontGroupCacheKey {
pointer: Arc<SpecifiedFontStyle>,
size: Au,
address: usize,
}
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]
pub fn invalidate_font_caches() {
FONT_CACHE_EPOCH.fetch_add(1, Ordering::SeqCst);