Last active
January 7, 2018 04:25
-
-
Save kirilloid/14ec1da29355b6dc0523743f600747e9 to your computer and use it in GitHub Desktop.
deep clone test suite
This file contains hidden or 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
var handlers = {}; | |
self.addEventListener('message', function (event) { | |
if (event.origin !== location.origin) return; | |
var key = event.data.key; | |
var value = event.data.value; | |
if (!handlers[key]) return; | |
handlers[key](value); | |
delete handlers[key]; | |
}); | |
var TIMEOUT_ERROR = new Error('timed out'); | |
function cloneViaPostMessage(arg) { | |
return new Promise(function (resolve, reject) { | |
var randomKey = Math.random().toString(36).slice(2); | |
handlers[randomKey] = resolve; | |
try { | |
self.postMessage({ key: randomKey, value: arg }, location.origin); | |
} catch(e) { | |
reject(e); | |
} | |
setTimeout(reject, 1000, TIMEOUT_ERROR); | |
}); | |
} |
This file contains hidden or 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
function deepClone(node) { | |
if (Array.isArray(node)) { | |
return node.map(deepClone); | |
} | |
if (typeof node !== 'object' | |
|| node === null) { | |
return node; | |
} | |
var copy = {}; | |
for (var key in node) { | |
copy[key] = deepClone(node[key]); | |
} | |
return copy; | |
} |
This file contains hidden or 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
// the call hirerarhcy is: suite > run > runIteration | |
var ITERATIONS_BASE = 1e6; // reduce it for slow browsers/methods | |
function jsonClone(x) { return JSON.parse(JSON.stringify(x)); } | |
function message(x) { window.postMessage(x, location.origin); } | |
function generateString () { return Math.random().toString(36).slice(2); } | |
function runIteration(maxDepth, maxKeys, copyFn) { | |
var totalKeys = 0; | |
function generate(depth) { | |
const num = depth / 2 + Math.floor(Math.random() * depth); | |
if (num === 0 || totalKeys >= maxKeys) { | |
totalKeys++; | |
return generateString(); | |
} | |
var obj; | |
// actually the proportion of arrays/objects almost doesn't affect executino time for most functions | |
if (Math.random() > 0.1) { | |
obj = {}; | |
for (var i = 0; i < num; i++) { | |
obj[generateString()] = generate(depth - 1); | |
} | |
} else { | |
obj = []; | |
for (var i = 0; i < num; i++) { | |
obj.push(generate(depth - 1)); | |
} | |
} | |
return obj; | |
} | |
var obj = generate(maxDepth); | |
// it generates slightly more nodes, but no more than maxKeys + depth, which is negligible | |
if (totalKeys < maxKeys) return; | |
var start = performance.now(); | |
copyFn(obj); | |
return performance.now() - start; | |
} | |
// stats utility functions | |
function avg(array) { | |
return array.reduce(function(a, b) { return a + b; }, 0) / array.length; | |
} | |
function disp(array) { | |
var avg2 = Math.pow(avg(array), 2); | |
var sq2 = array.reduce(function (a, e) { return a + e * e - avg2; }, 0); | |
return Math.sqrt(sq2) / array.length; | |
} | |
function run(copyFn, iterations, maxDepth, maxKeys) { | |
var times = []; | |
while (times.length < iterations * 1.2) { | |
var time = runIteration(maxDepth, maxKeys, copyFn); | |
if (time) times.push(time); | |
} | |
// remove top and bottom 1/12 | |
times = times | |
.sort(function (a, b) { return a - b; }) | |
.slice(iterations * .1, -iterations * .1); | |
return { | |
avg: avg(times), | |
// actual results seem suspiciously small, but gives some estimations anyway | |
disp: 3 * disp(times) | |
}; | |
} | |
function suite(copyFn) { | |
[ | |
{ depth: 10, nodes: 1000 }, | |
{ depth: 10, nodes: 2000 }, | |
{ depth: 11, nodes: 3000 }, | |
{ depth: 11, nodes: 5000 }, | |
{ depth: 11, nodes: 7000 }, | |
{ depth: 12, nodes: 10000 }, | |
{ depth: 12, nodes: 14000 }, | |
{ depth: 12, nodes: 20000 }, | |
{ depth: 13, nodes: 30000 }, | |
{ depth: 13, nodes: 50000 }, | |
{ depth: 13, nodes: 70000 }, | |
{ depth: 13, nodes: 100000 } | |
].forEach(function (params) { | |
var depth = params.depth; | |
var nodes = params.nodes; | |
var iterations = Math.max(20, Math.round(ITERATIONS_BASE / nodes / 10) * 10); | |
console.log(nodes, run(copyFn, iterations, depth, nodes)); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment