Skip to content

Instantly share code, notes, and snippets.

@crystalline
Created April 16, 2019 23:54
Show Gist options
  • Save crystalline/74ed077f067e6c4b55dd076d4e62a3fd to your computer and use it in GitHub Desktop.
Save crystalline/74ed077f067e6c4b55dd076d4e62a3fd to your computer and use it in GitHub Desktop.
A comparison of redux's compose higher order function and a simple imperative implementation on a synthetic benchmark (results: as of 2019 the imperative implementation is 3-5 times faster)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Compose performance benchmark</title>
</head>
<body onload="run();">
<script>
function log(...args) {
document.body.innerHTML += `<div>${args.join(' ')}</div>`
}
function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
function _compose(...funcs) {
const N = funcs.length;
if (N === 0) {
return arg => arg
}
if (N === 1) {
return funcs[0]
}
return (...args) => {
let temp = funcs[N-1](...args);
for (let i=1; i<N; i++) {
temp = funcs[N-1-i](temp);
}
return temp;
}
}
const N = 3000000;
function test(x) {
return x+1;
}
function test_A() {
let temp = 1;
for (let i=0; i<N; i++) {
temp = _compose(test,test,test,test,test,test,test,test)(temp);
}
return temp;
}
function test_B() {
let temp = 1;
for (let i=0; i<N; i++) {
temp = compose(test,test,test,test,test,test,test,test)(temp);
}
return temp;
}
function timeExec(f) {
const t0 = Date.now();
let val = f();
const t1 = Date.now();
log('Execution took',t1-t0,'ms');
}
function run() {
log('Testing FB\'s compose');
timeExec(test_B);
log('Testing my compose');
timeExec(test_A);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment