diff --git a/www/js/lib/filecache.js b/www/js/lib/filecache.js index e87bd883..d9e10406 100644 --- a/www/js/lib/filecache.js +++ b/www/js/lib/filecache.js @@ -50,7 +50,8 @@ define(['q'], function(Q) { * LRUCache implemnentation with Map adapted from https://markmurray.co/blog/lru-cache/ */ function LRUCache() { - console.log('Creating cache of size ' + MAX_CACHE_SIZE + ' * ' + BLOCK_SIZE + ' bytes'); + /** CACHE TUNING **/ + // console.log('Creating cache of size ' + MAX_CACHE_SIZE + ' * ' + BLOCK_SIZE + ' bytes'); // Initialize persistent Cache properties this.capacity = MAX_CACHE_SIZE; this.cache = new Map(); @@ -79,12 +80,14 @@ define(['q'], function(Q) { * @param {Uint8Array} value The value to store in the cache */ LRUCache.prototype.store = function (key, value) { + // We get the existing entry's object for memory-management purposes; if it exists, it will contain identical data + // to , but is strongly referenced by the Map. (It should be rare that two async Promises attempt to + // store the same data in the Cache, once the Cache is sufficiently populated.) var entry = this.cache.get(key); - // If the key already exists, delete it so that it will be added + // If the key already exists, delete it and re-insert it, so that it will be added // to the bottom of the Map (bottom = most recent) if (entry) this.cache.delete(key); else entry = value; - // Store a reference to the entry in the Map this.cache.set(key, entry); // If we've exceeded the cache capacity, then delete the least recently accessed value, // which will be the item at the top of the Map, i.e the first position @@ -93,11 +96,11 @@ define(['q'], function(Q) { var firstKey = this.cache.keys().next().value; this.cache.delete(firstKey); } else { - // IE11 doesn't support the keys iterator, so we have to do forEach loop through all 4000 entries + // IE11 doesn't support the keys iterator, so we have to do a forEach loop through all 4000 entries // to get the oldest values. To prevent excessive iterations, we delete 25% at a time. var q = Math.floor(0.25 * this.capacity); var c = 0; - console.log('Deleteing ' + q + ' cache entries'); + // console.log('Deleteing ' + q + ' cache entries'); this.cache.forEach(function (v, k, map) { if (c > q) return; map.delete(k); @@ -113,9 +116,11 @@ define(['q'], function(Q) { */ var cache = new LRUCache(); - // Counters for reporting only - var hits = 0; - var misses = 0; + /** CACHE TUNING **/ + + // DEV: Uncomment this block and blocks below marked 'CACHE TUNING' to measure Cache hit and miss rates for different Cache sizes + // var hits = 0; + // var misses = 0; /** * Read a certain byte range in the given file, breaking the range into chunks that go through the cache @@ -137,7 +142,8 @@ define(['q'], function(Q) { var block = cache.get(file.id + ':' + id); if (block === undefined) { // Data not in cache, so read from archive - misses++; + /** CACHE TUNING **/ + // misses++; // DEV: This is a self-calling function, i.e. the function is called with an argument of which then // becomes the parameter readRequests.push(function(offset) { @@ -147,15 +153,18 @@ define(['q'], function(Q) { }); }(id)); } else { - hits++; + /** CACHE TUNING **/ + // hits++; blocks[id] = block; } } - if (misses + hits > 2000) { - console.log("** Block cache hit rate: " + Math.round(hits / (hits + misses) * 1000) / 10 + "% [ hits:" + hits + " / misses:" + misses + " ]"); - hits = 0; - misses = 0; - } + /** CACHE TUNING **/ + // if (misses + hits > 2000) { + // console.log('** Block cache hit rate: ' + Math.round(hits / (hits + misses) * 1000) / 10 + '% [ hits:' + hits + + // ' / misses:' + misses + ' ] Size: ' + cache.cache.size); + // hits = 0; + // misses = 0; + // } // Wait for all the blocks to be read either from the cache or from the archive return Q.all(readRequests).then(function() { var result = new Uint8Array(end - begin);