diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-03-16 19:31:38 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-03-16 20:51:50 +0000 |
commit | 9c80392ac415e7f07c71261d280ac4376d3c8471 (patch) | |
tree | 06e215c968816e5bb18c5400b5b895572e6f8c5e /src/cairo-cache.c | |
parent | 121d4bb656755b7ca89065bf87e3e4e47c49c89d (diff) | |
download | cairo-9c80392ac415e7f07c71261d280ac4376d3c8471.tar.gz |
[scaled-font] Lean and mean global glyph cache.
Jeff Muizelaar pointed out that the severe overallocation implicit in the
current version of the glyph cache is obnoxious and prevents him from
accepting the trunk into Mozilla. Jeff captured a trace of scaled font
and glyph usage during a tp run and presented his analysis in
http://lists.cairographics.org/archives/cairo/2009-March/016706.html
Using that data, the design was changed to allocate pages of glyphs from a
capped global pool but with per-font hash tables. This should allow the
glyph cache to have tight memory bounds with fair allocation according to
usage. Note that both the old design and the 1.8 glyph cache had
essentially unbounded memory constraints, since each scaled font could
cache up to 256 glyphs (1.8) or had a reserved page (old), with no limit
on the number of active fonts. Currently the eviction policy is a simple
random strategy, this gives a 'fair' allotment of the cache, but a LRU
variant might perform better.
On a sample run of firefox-3.0.7 perusing BBC news in 32 languages:
1.8: cache allocation 8190x, ~1.2 MiB; elapsed 88.2s
old: cache allocation 771x, ~13.8 MiB; elapsed 81.7s
lean: cache allocation 433x, ~1.8 MiB; elapsed 82.4s
Diffstat (limited to 'src/cairo-cache.c')
-rw-r--r-- | src/cairo-cache.c | 39 |
1 files changed, 17 insertions, 22 deletions
diff --git a/src/cairo-cache.c b/src/cairo-cache.c index cab6e1e9f..7542242dc 100644 --- a/src/cairo-cache.c +++ b/src/cairo-cache.c @@ -42,9 +42,16 @@ static void _cairo_cache_shrink_to_accommodate (cairo_cache_t *cache, unsigned long additional); +static cairo_bool_t +_cairo_cache_entry_is_non_zero (const void *entry) +{ + return ((const cairo_cache_entry_t *) entry)->size; +} + static cairo_status_t _cairo_cache_init (cairo_cache_t *cache, cairo_cache_keys_equal_func_t keys_equal, + cairo_cache_predicate_func_t predicate, cairo_destroy_func_t entry_destroy, unsigned long max_size) { @@ -52,6 +59,9 @@ _cairo_cache_init (cairo_cache_t *cache, if (unlikely (cache->hash_table == NULL)) return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (predicate == NULL) + predicate = _cairo_cache_entry_is_non_zero; + cache->predicate = predicate; cache->entry_destroy = entry_destroy; cache->max_size = max_size; @@ -114,6 +124,7 @@ _cairo_cache_fini (cairo_cache_t *cache) **/ cairo_cache_t * _cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal, + cairo_cache_predicate_func_t predicate, cairo_destroy_func_t entry_destroy, unsigned long max_size) { @@ -126,7 +137,11 @@ _cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal, return NULL; } - status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size); + status = _cairo_cache_init (cache, + keys_equal, + predicate, + entry_destroy, + max_size); if (unlikely (status)) { free (cache); return NULL; @@ -221,26 +236,6 @@ _cairo_cache_lookup (cairo_cache_t *cache, (cairo_hash_entry_t *) key); } -void * -_cairo_cache_steal (cairo_cache_t *cache, - cairo_cache_entry_t *key) -{ - cairo_cache_entry_t *entry; - - entry = _cairo_hash_table_steal (cache->hash_table, - (cairo_hash_entry_t *) key); - if (entry != NULL) - cache->size -= entry->size; - - return entry; -} - -static cairo_bool_t -_cairo_cache_entry_is_non_zero (void *entry) -{ - return ((cairo_cache_entry_t *)entry)->size; -} - /** * _cairo_cache_remove_random: * @cache: a cache @@ -256,7 +251,7 @@ _cairo_cache_remove_random (cairo_cache_t *cache) cairo_cache_entry_t *entry; entry = _cairo_hash_table_random_entry (cache->hash_table, - _cairo_cache_entry_is_non_zero); + cache->predicate); if (unlikely (entry == NULL)) return FALSE; |