Merge pull request #566 from juliandescottes/memory-improvements

Memory improvements
This commit is contained in:
Julian Descottes 2016-11-22 00:27:33 +01:00 committed by GitHub
commit 5996216ae7
4 changed files with 60 additions and 8 deletions

View File

@ -1,8 +1,8 @@
(function () {
var ns = $.namespace('pskl.model.frame');
// 10 * 60 * 1000 = 10 minutes
var DEFAULT_CLEAR_INTERVAL = 10 * 60 * 1000;
// Maximum number of cache entries
var MAX_CACHE_ENTRIES = 100;
var DEFAULT_FRAME_PROCESSOR = function (frame) {
return pskl.utils.FrameUtils.toImage(frame);
@ -12,14 +12,16 @@
var DEFAULT_NAMESPACE = '__cache_default__';
ns.CachedFrameProcessor = function (cacheResetInterval) {
ns.CachedFrameProcessor = function () {
// Cache object.
this.cache_ = {};
this.cacheResetInterval = cacheResetInterval || DEFAULT_CLEAR_INTERVAL;
// Array of [namespace, key] for each cached frame.
this.cacheQueue_ = [];
this.frameProcessor = DEFAULT_FRAME_PROCESSOR;
this.outputCloner = DEFAULT_OUTPUT_CLONER;
this.defaultNamespace = DEFAULT_NAMESPACE;
window.setInterval(this.clear.bind(this), this.cacheResetInterval);
};
ns.CachedFrameProcessor.prototype.clear = function () {
@ -69,6 +71,11 @@
} else {
processedFrame = this.frameProcessor(frame);
cache[cacheKey] = processedFrame;
this.cacheQueue_.unshift([namespace, cacheKey]);
if (this.cacheQueue_.length > MAX_CACHE_ENTRIES) {
var oldestItem = this.cacheQueue_.pop();
this.cache_[oldestItem[0]][oldestItem[1]] = null;
}
}
return processedFrame;

View File

@ -10,11 +10,16 @@
this.cachedFrameProcessor = new pskl.model.frame.AsyncCachedFrameProcessor();
this.cachedFrameProcessor.setFrameProcessor(this.getFrameColors_.bind(this));
this.throttledUpdateCurrentColors_ = pskl.utils.FunctionUtils.throttle(
this.updateCurrentColors_.bind(this),
1000
);
this.paletteService = pskl.app.paletteService;
};
ns.CurrentColorsService.prototype.init = function () {
$.subscribe(Events.HISTORY_STATE_SAVED, this.updateCurrentColors_.bind(this));
$.subscribe(Events.HISTORY_STATE_SAVED, this.throttledUpdateCurrentColors_);
$.subscribe(Events.HISTORY_STATE_LOADED, this.loadColorsFromCache_.bind(this));
};

View File

@ -24,6 +24,9 @@
// Interval/buffer (in milliseconds) between two state load (ctrl+z/y spamming)
ns.HistoryService.LOAD_STATE_INTERVAL = 50;
// Maximum number of states that can be recorded.
ns.HistoryService.MAX_SAVED_STATES = 500;
ns.HistoryService.prototype.init = function () {
$.subscribe(Events.PISKEL_SAVE_STATE, this.onSaveStateEvent.bind(this));
@ -41,7 +44,6 @@
};
ns.HistoryService.prototype.saveState = function (action) {
this.stateQueue = this.stateQueue.slice(0, this.currentIndex + 1);
this.currentIndex = this.currentIndex + 1;
var state = {
@ -58,6 +60,13 @@
state.piskel = this.serializer.serialize(piskel);
}
// If the new state pushes over MAX_SAVED_STATES, erase all states between the first and
// second snapshot states.
if (this.stateQueue.length > ns.HistoryService.MAX_SAVED_STATES) {
var firstSnapshotIndex = this.getNextSnapshotIndex_(1);
this.stateQueue.splice(0, firstSnapshotIndex);
this.currentIndex = this.currentIndex - firstSnapshotIndex;
}
this.stateQueue.push(state);
$.publish(Events.HISTORY_STATE_SAVED);
};
@ -92,6 +101,13 @@
return index;
};
ns.HistoryService.prototype.getNextSnapshotIndex_ = function (index) {
while (this.stateQueue[index] && !this.stateQueue[index].piskel) {
index = index + 1;
}
return index;
};
ns.HistoryService.prototype.loadState = function (index) {
try {
if (this.isLoadStateAllowed_(index)) {

View File

@ -2,6 +2,9 @@
var ns = $.namespace('pskl.utils');
ns.FunctionUtils = {
/**
* Returns a memoized version of the provided function.
*/
memo : function (fn, cache, scope) {
var memoized = function () {
var key = Array.prototype.join.call(arguments, '-');
@ -11,6 +14,27 @@
return cache[key];
};
return memoized;
},
/**
* Returns a throttled version of the provided method, that will be called at most
* every X milliseconds, where X is the provided interval.
*/
throttle : function (fn, interval) {
var last, timer;
return function () {
var now = Date.now();
if (last && now < last + interval) {
clearTimeout(timer);
timer = setTimeout(function () {
last = now;
fn();
}, interval);
} else {
last = now;
fn();
}
};
}
};
})();