From ef9ab9458027d5ed3480447725f54aa51d180a40 Mon Sep 17 00:00:00 2001 From: Ashod Nakashian Date: Sun, 27 Nov 2016 00:59:04 -0500 Subject: [PATCH] loolwsd: less aggressive png cache eviction The overall hit-rate improves significantly when we don't remove entries too soon. Here we give entries more time to show their merrit. There are now two limits, soft and hard. The former is used to remove entries with no hits at all, while the latter is used to avoid overflowing the cache footprint too much. Entries also get started with a single hit, which prevents them getting evicted too soon (i.e. right after getting added). Finally, there is no longer need to reduce the hit count of entries too agressively since we have two tiers (soft and hard limits) and zero-hit entries are removed before others. The average cache size while auto-typing in Writer doc is less than 180kb, which is 1.4x the original size of 128kb. Change-Id: I946318151638c9c64c714190084c492f9098852b Reviewed-on: https://gerrit.libreoffice.org/31291 Reviewed-by: Ashod Nakashian Tested-by: Ashod Nakashian --- kit/Kit.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/kit/Kit.cpp b/kit/Kit.cpp index 68099cfcc..0836b1e3d 100644 --- a/kit/Kit.cpp +++ b/kit/Kit.cpp @@ -271,13 +271,15 @@ class PngCache size_t _hitCount; CacheData _data; CacheEntry(size_t defaultSize) : - _hitCount(0), + _hitCount(1), // Every entry is used at least once; prevent removal at birth. _data( new std::vector< char >() ) { _data->reserve( defaultSize ); } } ; size_t _cacheSize; + static const size_t CacheSizeSoftLimit = (1024 * 4 * 32); // 128k of cache + static const size_t CacheSizeHardLimit = CacheSizeSoftLimit * 2; size_t _cacheHits; size_t _cacheTests; std::map< uint64_t, CacheEntry > _cache; @@ -286,7 +288,7 @@ class PngCache { // A normalish PNG image size for text in a writer document is // around 4k for a content tile, and sub 1k for a background one. - if (_cacheSize > (1024 * 4 * 32) /* 128k of cache */) + if (_cacheSize > CacheSizeHardLimit) { size_t avgHits = 0; for (auto it = _cache.begin(); it != _cache.end(); ++it) @@ -299,14 +301,18 @@ class PngCache for (auto it = _cache.begin(); it != _cache.end();) { - if (it->second._hitCount <= avgHits) + if ((_cacheSize > CacheSizeSoftLimit && it->second._hitCount == 0) || + (_cacheSize > CacheSizeHardLimit && it->second._hitCount > 0 && it->second._hitCount <= avgHits)) { + // Shrink cache when we exceed the size to maximize + // the chance of hitting these entries in the future. _cacheSize -= it->second._data->size(); it = _cache.erase(it); } else { - it->second._hitCount /= 2; + if (it->second._hitCount > 0) + it->second._hitCount--; ++it; } }