From 3da09b93b771df49ba8ff88006b96e4836202e71 Mon Sep 17 00:00:00 2001 From: Thaddee Tyl Date: Sun, 27 Apr 2014 23:47:12 +0000 Subject: [PATCH] Separated the LRU cache implementation. --- lru-cache.js | 45 +++++++++++++++++++++++++++++++++++++++++++++ svg-to-img.js | 34 +++++----------------------------- 2 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 lru-cache.js diff --git a/lru-cache.js b/lru-cache.js new file mode 100644 index 0000000000..b01dd9ccc1 --- /dev/null +++ b/lru-cache.js @@ -0,0 +1,45 @@ +// Cache any data with a timestamp, +// remove only the oldest data. + +function Cache(size) { + if (!this instanceof Cache) { return new Cache(size); } + this.size = size; + this.cache = Object.create(null); + this.cacheTime = Object.create(null); + this.cacheSize = 0; +} + +Cache.prototype.set = +function addToCache(cacheIndex, cached) { + this.cache[cacheIndex] = cached; + var mostAncient = +(new Date()); + this.cacheTime[cacheIndex] = mostAncient; + if (this.cacheSize >= this.size) { + // Find the most ancient image. + var ancientCacheIndex = cacheIndex; + for (var currentCacheIndex in this.cacheTime) { + if (mostAncient > this.cacheTime[currentCacheIndex]) { + mostAncient = this.cacheTime[currentCacheIndex]; + ancientCacheIndex = currentCacheIndex; + } + } + // Delete that image. + delete this.cache[ancientCacheIndex]; + delete this.cacheTime[ancientCacheIndex]; + } else { + this.cacheSize++; + } +} + +Cache.prototype.get = +function getFromCache(cacheIndex) { + this.cacheTime[cacheIndex] = +(new Date()); + return this.cache[cacheIndex]; +} + +Cache.prototype.has = +function hasInCache(cacheIndex) { + return this.cache[cacheIndex] !== undefined; +} + +module.exports = Cache; diff --git a/svg-to-img.js b/svg-to-img.js index eac8d52c03..662bbb84a6 100644 --- a/svg-to-img.js +++ b/svg-to-img.js @@ -2,21 +2,18 @@ var fs = require('fs'); var os = require('os'); var path = require('path'); var phantom = require('phantomjs'); +var LruCache = require('./lru-cache.js'); var childProcess = require('child_process'); var phantomScript = path.join(__dirname, 'phantomjs-svg2png.js'); -var imgCache = Object.create(null); -var imgCacheTime = Object.create(null); -var imgCacheSize = 0; // The following is an arbitrary limit (~1.5MB, 1.5kB/image). -var imgCacheMaxSize = 1000; +var imgCache = new LruCache(1000); module.exports = function (svg, format, out, cb) { var cacheIndex = format + svg; - if (imgCache[cacheIndex] !== undefined) { + if (imgCache.has(cacheIndex)) { // We own a cache for this svg conversion. - (new DataStream(imgCache[cacheIndex])).pipe(out); - imgCacheTime[cacheIndex] = +(new Date()); + (new DataStream(imgCache.get(cacheIndex))).pipe(out); return; } var tmpFile = path.join(os.tmpdir(), @@ -36,33 +33,12 @@ module.exports = function (svg, format, out, cb) { // Remove the temporary file after use. inStream.on('end', function() { try { out.end(); } catch(e) {} - addToCache(cacheIndex, cached); + imgCache.set(cacheIndex, cached); fs.unlink(tmpFile, cb); }); }); }; -function addToCache(cacheIndex, cached) { - imgCache[cacheIndex] = cached; - var mostAncient = +(new Date()); - imgCacheTime[cacheIndex] = mostAncient; - if (imgCacheSize >= imgCacheMaxSize) { - // Find the most ancient image. - var ancientCacheIndex = cacheIndex; - for (var currentCacheIndex in imgCacheTime) { - if (mostAncient > imgCacheTime[currentCacheIndex]) { - mostAncient = imgCacheTime[currentCacheIndex]; - ancientCacheIndex = currentCacheIndex; - } - } - // Delete that image. - delete imgCache[ancientCacheIndex]; - delete imgCacheTime[ancientCacheIndex]; - } else { - imgCacheSize++; - } -} - // Fake stream from the cache. var Readable = require('stream').Readable; var util = require('util');