Eliminate CPU churning on cache highwater check

On older machines loading high portal dense areas this check is
using 70-90% of CPU in Object.keys(cache).length, leading to
resource starvation, and refresh times up to 10 times longer.

The LRU cache high-water mark is checked every time we receive portal
state from the intel servers to see if we need to do GC. In
my case this peaks out  500-1000 portal adds per second on
an aging laptop with the existing code with chrome-unstable,
and minimal IITC plugins.  GC itself (ignoring v8 GC) was only
taking 15ms, amortized to about 15usec a portal.

Unforutnately the Object.keys(cache).length check was taking
2-3ms each portal add, and 70-90% of the main thread was spent
there, grinding older machines to a halt.

I've just added a counter to track adds to the cache, and am
updating it with the real cache size on GC (the two checks
are almost always identical in higher density areas, and
won't lead to performance issues if cache adds are over-
estimated).

Effects:
 - pushPortalGuidPositionCache goes from using the majority
   of CPU when loading dense areas to almost nothing.

 - Older machines can actually view western europe without
   grinding the browser to a halt.

 - the cache itself is now hitting GC_LIMIT in less than
   100ms on my old laptop.  (I think increasing GC_LIMIT
   to 80,000 and GC_KEEP to 40,000 is going to put less
   load on the Javascript engine GC, and have the cache
   be useful still, but I left that out of the PR as it's
   slightly more subjective)

 - v8's GC is being slammed slightly less often than normal
   (it's still thrashing, but this isn't the main culprit)

The patch has been tested by about half a dozen people
using different blends of IITC plugins on both Chrome,
Firefox and across different OSs and with very different
hardware. Reports ranged from minor to (more often) huge
improvements in load speed and responsiveness in high
density areas.
This commit is contained in:
eidyia 2015-03-08 03:01:54 +11:00
parent b6c89c9575
commit fe19227839

View File

@ -93,6 +93,7 @@ window.findPortalLatLng = function(guid) {
(function() { (function() {
var cache = {}; var cache = {};
var cache_level = 0;
var GC_LIMIT = 5000; // run garbage collector when cache has more that 5000 items var GC_LIMIT = 5000; // run garbage collector when cache has more that 5000 items
var GC_KEEP = 4000; // keep the 4000 most recent items var GC_KEEP = 4000; // keep the 4000 most recent items
@ -128,13 +129,15 @@ window.findPortalLatLng = function(guid) {
window.pushPortalGuidPositionCache = function(guid, latE6, lngE6) { window.pushPortalGuidPositionCache = function(guid, latE6, lngE6) {
cache[latE6+","+lngE6] = [guid, Date.now()]; cache[latE6+","+lngE6] = [guid, Date.now()];
cache_level += 1;
if(Object.keys(cache).length > GC_LIMIT) { if(cache_level > GC_LIMIT) {
Object.keys(cache) // get all latlngs Object.keys(cache) // get all latlngs
.map(function(latlng) { return [latlng, cache[latlng][1]]; }) // map them to [latlng, timestamp] .map(function(latlng) { return [latlng, cache[latlng][1]]; }) // map them to [latlng, timestamp]
.sort(function(a,b) { return b[1] - a[1]; }) // sort them .sort(function(a,b) { return b[1] - a[1]; }) // sort them
.slice(GC_KEEP) // drop the MRU .slice(GC_KEEP) // drop the MRU
.forEach(function(item) { delete cache[item[0]] }); // delete the rest .forEach(function(item) { delete cache[item[0]] }); // delete the rest
cache_level = Object.keys(cache).length
} }
} }
})(); })();