Autocleanup cached filters when over 10k items (a few MB)

Precaution for the [rare but possible] case of users running Stylus for a very long time without restarting the browser.
This commit is contained in:
tophf 2017-03-22 08:12:11 +03:00
parent c54e22ad64
commit 95e2263c10

View File

@ -175,9 +175,11 @@ function filterStyles(options = {}) {
const cached = cachedStyles.filters.get(cacheKey);
if (cached) {
//console.log('%c%s filterStyles REUSED RESPONSE %s', 'color:gray', (performance.now() - t0).toFixed(1), JSON.stringify(options))
cached.hits++;
cached.lastHit = Date.now();
return asHash
? Object.assign({disableAll: prefs.get('disableAll', false)}, cached)
: cached;
? Object.assign({disableAll: prefs.get('disableAll', false)}, cached.styles)
: cached.styles;
}
const styles = id == null
@ -204,13 +206,50 @@ function filterStyles(options = {}) {
}
}
//console.log('%s filterStyles %s', (performance.now() - t0).toFixed(1), JSON.stringify(options))
cachedStyles.filters.set(cacheKey, filtered);
cachedStyles.filters.set(cacheKey, {
styles: filtered,
lastHit: Date.now(),
hits: 1,
});
if (cachedStyles.filters.size > 10000) {
cleanupCachedFilters();
}
return asHash
? Object.assign({disableAll: prefs.get('disableAll', false)}, filtered)
: filtered;
}
function cleanupCachedFilters({force = false} = {}) {
if (!force) {
// sliding timer for 1 second
clearTimeout(cleanupCachedFilters.timeout);
cleanupCachedFilters.timeout = setTimeout(cleanupCachedFilters, 1000, {force: true});
return;
}
const size = cachedStyles.filters.size;
const oldestHit = cachedStyles.filters.values().next().value.lastHit;
const now = Date.now();
const timeSpan = now - oldestHit;
const recencyWeight = 5 / size;
const hitWeight = 1 / 4; // we make ~4 hits per URL
const lastHitWeight = 10;
// delete the oldest 10%
const sorted = [...cachedStyles.filters.entries()]
.map(([id, v], index) => ({
id,
weight:
index * recencyWeight +
v.hits * hitWeight +
(v.lastHit - oldestHit) / timeSpan * lastHitWeight,
}))
.sort((a, b) => a.weight - b.weight)
.slice(0, size / 10 + 1)
.forEach(({id}) => cachedStyles.filters.delete(id));
cleanupCachedFilters.timeout = 0;
}
function saveStyle(style, {notify = true} = {}) {
return new Promise(resolve => {
getDatabase(db => {