Created
May 17, 2016 14:58
-
-
Save louisremi/8987ec055d00a33d72f45d8fd9e82daf to your computer and use it in GitHub Desktop.
Caching strategies (https://jsbench.github.io/#8987ec055d00a33d72f45d8fd9e82daf) #jsbench #jsperf
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"/> | |
<title>Caching strategies</title> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script> | |
<script src="./suite.js"></script> | |
</head> | |
<body> | |
<h1>Open the console to view the results</h1> | |
<h2><code>cmd + alt + j</code> or <code>ctrl + alt + j</code></h2> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
(function (factory) { | |
if (typeof Benchmark !== "undefined") { | |
factory(Benchmark); | |
} else { | |
factory(require("benchmark")); | |
} | |
})(function (Benchmark) { | |
var suite = new Benchmark.Suite; | |
Benchmark.prototype.setup = function () { | |
function Cache1(limit) { | |
this.limit = limit || 1000; | |
this.map = new Map(); | |
} | |
Cache1.prototype.set = function(key, value) { | |
this.map.delete(key); | |
this.map.set(key, value); | |
if ( this.map.size > this.limit ) { | |
this.map.delete( this.map.keys().next().value ); | |
} | |
return this; | |
}; | |
Cache1.prototype.get = function(key) { | |
if ( this.map.has(key) ) { | |
var value = this.map.get(key); | |
this.map.delete(key); | |
this.map.set(key, value); | |
return value; | |
} | |
}; | |
Cache1.prototype.clear = function() { | |
this.map.clear(); | |
}; | |
function Cache2(limit) { | |
this.size = 0; | |
this.limit = limit || 1000; | |
this.map = {}; | |
this.head = null; | |
this.tail = null; | |
} | |
Cache2.prototype._setHead = function(node) { | |
node.next = this.head; | |
node.prev = null; | |
if (this.head !== null) { | |
this.head.prev = node; | |
} | |
this.head = node; | |
if (this.tail === null) { | |
this.tail = node; | |
} | |
this.size++; | |
this.map[node.key] = node; | |
} | |
Cache2.prototype.set = function(key, value) { | |
if (key in this.map) { | |
this.map[key].value = value; | |
this.remove(key); | |
} else { | |
if (this.size >= this.limit) { | |
delete this.map[this.tail.key]; | |
this.size--; | |
this.tail = this.tail.prev; | |
this.tail.next = null; | |
} | |
} | |
this._setHead({ key: key, value: value }); | |
return this; | |
}; | |
Cache2.prototype.get = function(key) { | |
if (key in this.map) { | |
var value = this.map[key].value; | |
var node = { key: key, value: value }; | |
this.remove(key); | |
this._setHead(node); | |
return value; | |
} | |
}; | |
Cache2.prototype.remove = function(key) { | |
if ( !(key in this.map) ) { | |
return false; | |
} | |
var node = this.map[key]; | |
if (node.prev != null) { | |
node.prev.next = node.next; | |
} else { | |
this.head = node.next; | |
} | |
if (node.next != null) { | |
node.next.prev = node.prev; | |
} else { | |
this.tail = node.prev; | |
} | |
delete this.map[key]; | |
this.size--; | |
return true; | |
}; | |
Cache2.prototype.clear = function() { | |
this.map = {}; | |
this.head = null; | |
this.tail = null; | |
}; | |
function Cache3(limit) { | |
this.map0 = new Map(); | |
this.map1 = new Map(); | |
this.limit = limit || 1000; | |
} | |
Cache3.prototype.set = function(key, value) { | |
this.map0.set(key, value); | |
// before the cache reaches it's max size, start filling a new cache | |
if ( this.map0.size > this.limit * 0.9 ) { | |
this.map1.set( key, value ); | |
} | |
// when the cache reaches its maximum size, swap it with the newest and | |
// clear it | |
if ( this.map0.size > this.limit ) { | |
var tmp = this.map0; | |
this.map0 = this.map1; | |
this.map1 = tmp; | |
this.map1.clear(); | |
} | |
return this; | |
}; | |
Cache3.prototype.get = function(key) { | |
return this.map0.get(key); | |
}; | |
Cache3.prototype.delete = function(key) { | |
this.map1.delete(key); | |
return this.map0.delete(key); | |
}; | |
Cache3.prototype.clear = function() { | |
this.map0.clear(); | |
this.map1.clear(); | |
} | |
var caches = [ | |
new Map(), | |
new Cache1(1000), | |
new Cache2(1000), | |
new Cache3(1000) | |
]; | |
caches.forEach(function(cache) { | |
for ( var i = 0; i < 1000; i++ ) { | |
cache.set(i, i * i); | |
} | |
}); | |
}; | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[0].get(key); | |
} | |
}); | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[1].get(key); | |
} | |
}); | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[2].get(key); | |
} | |
}); | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[3].get(key); | |
} | |
}); | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[0].set(key, key * key); | |
} | |
}); | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[1].set(key, key * key); | |
} | |
}); | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[2].set(key, key * key); | |
} | |
}); | |
suite.add("var key = Math.round(Math.random() * 1000);", function () { | |
var key = Math.round(Math.random() * 1000); | |
if ( Math.random() > 0 ) { | |
caches[3].set(key, key * key); | |
} | |
}); | |
suite.on("cycle", function (evt) { | |
console.log(" - " + evt.target); | |
}); | |
suite.on("complete", function (evt) { | |
console.log(new Array(30).join("-")); | |
var results = evt.currentTarget.sort(function (a, b) { | |
return b.hz - a.hz; | |
}); | |
results.forEach(function (item) { | |
console.log((idx + 1) + ". " + item); | |
}); | |
}); | |
console.log("Caching strategies"); | |
console.log(new Array(30).join("-")); | |
suite.run(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment