Created
December 31, 2022 01:21
-
-
Save baetheus/ec8b243a6b52175bfc1dc5a6532355ec to your computer and use it in GitHub Desktop.
Pipe and Flow benchmarks
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
cpu: Apple M1 Max | |
runtime: deno 1.29.1 (aarch64-apple-darwin) | |
file:///Users/brandon/src/fun/main/benchmarks/fn.bench.ts | |
benchmark time (avg) (min … max) p75 p99 p995 | |
------------------------------------------------------------- ----------------------------- | |
flowOptimized 262.67 ns/iter (251.3 ns … 443.08 ns) 259.91 ns 312.58 ns 341.9 ns | |
flowReduceConst 404.92 ns/iter (395.69 ns … 504.78 ns) 402.08 ns 504.4 ns 504.78 ns | |
flowReduceFunction 510.3 ns/iter (504.26 ns … 540.63 ns) 510.64 ns 539.74 ns 540.63 ns | |
summary | |
flowOptimized | |
1.54x faster than flowReduceConst | |
1.94x faster than flowReduceFunction | |
pipeOptimized 366.84 ns/iter (359.47 ns … 392.71 ns) 369.27 ns 380.52 ns 392.71 ns | |
pipeReduceConst 49.69 ns/iter (47.95 ns … 61.04 ns) 49.53 ns 53.88 ns 54.52 ns | |
pipeReduceFunction 49.73 ns/iter (47.7 ns … 71.98 ns) 50.04 ns 54.79 ns 56.93 ns | |
pipeFlowConst 368.93 ns/iter (363.48 ns … 399.81 ns) 369.3 ns 394.82 ns 399.81 ns | |
pipeFlowFunction 369.02 ns/iter (363.79 ns … 388.21 ns) 370.1 ns 384.15 ns 388.21 ns | |
pipeFlowConstConst 372.85 ns/iter (369.32 ns … 391.8 ns) 373.29 ns 384.95 ns 391.8 ns | |
pipeFlowConstFunction 378.24 ns/iter (374.59 ns … 393.22 ns) 378.72 ns 393.07 ns 393.22 ns | |
summary | |
pipeReduceConst | |
1x faster than pipeReduceFunction | |
7.38x faster than pipeOptimized | |
7.42x faster than pipeFlowConst | |
7.43x faster than pipeFlowFunction | |
7.5x faster than pipeFlowConstConst | |
7.61x faster than pipeFlowConstFunction |
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
// | |
// deno-lint-ignore no-explicit-any | |
type AnyFn = (d: any) => any; | |
const add = (n: number) => n * n; | |
export function flow( | |
...[ab, bc, cd, de, ef, fg, gh, hi, ij, jk, kl, ...rest]: AnyFn[] | |
): AnyFn { | |
switch (arguments.length) { | |
case 1: | |
return (...as) => ab(...as); | |
case 2: | |
return (...as) => bc(ab(...as)); | |
case 3: | |
return (...as) => cd(bc(ab(...as))); | |
case 4: | |
return (...as) => de(cd(bc(ab(...as)))); | |
case 5: | |
return (...as) => ef(de(cd(bc(ab(...as))))); | |
case 6: | |
return (...as) => fg(ef(de(cd(bc(ab(...as)))))); | |
case 7: | |
return (...as) => gh(fg(ef(de(cd(bc(ab(...as))))))); | |
case 8: | |
return (...as) => hi(gh(fg(ef(de(cd(bc(ab(...as)))))))); | |
case 9: | |
return (...as) => ij(hi(gh(fg(ef(de(cd(bc(ab(...as))))))))); | |
case 10: | |
return (...as) => jk(ij(hi(gh(fg(ef(de(cd(bc(ab(...as)))))))))); | |
case 11: | |
return (...as) => kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(...as))))))))))); | |
default: | |
return (...as) => | |
rest.reduce( | |
(val, fn) => fn(val), | |
kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(...as))))))))))), | |
); | |
} | |
} | |
function pipe( | |
...[a, ab, bc, cd, de, ef, fg, gh, hi, ij, jk, kl, ...rest]: [ | |
unknown, | |
...AnyFn[], | |
] | |
): unknown { | |
switch (arguments.length) { | |
case 0: | |
return undefined; | |
case 1: | |
return a; | |
case 2: | |
return ab(a); | |
case 3: | |
return bc(ab(a)); | |
case 4: | |
return cd(bc(ab(a))); | |
case 5: | |
return de(cd(bc(ab(a)))); | |
case 6: | |
return ef(de(cd(bc(ab(a))))); | |
case 7: | |
return fg(ef(de(cd(bc(ab(a)))))); | |
case 8: | |
return gh(fg(ef(de(cd(bc(ab(a))))))); | |
case 9: | |
return hi(gh(fg(ef(de(cd(bc(ab(a)))))))); | |
case 10: | |
return ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))); | |
case 11: | |
return jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))); | |
case 12: | |
return kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))); | |
default: | |
return rest.reduce( | |
(val, fn) => fn(val), | |
kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))), | |
); | |
} | |
} | |
const flowConst = (...[fn, ...fns]: [AnyFn, ...AnyFn[]]): AnyFn => (...args) => | |
fns.reduce((a, f) => f(a), fn(...args)); | |
function flowFn(...[fn, ...fns]: [AnyFn, ...AnyFn[]]): AnyFn { | |
return (...args) => fns.reduce((a, f) => f(a), fn(...args)); | |
} | |
const pipeConst = (value: unknown, ...fns: AnyFn[]): unknown => | |
fns.reduce((val, fn) => fn(val), value); | |
function pipeFn(value: unknown, ...fns: AnyFn[]): unknown { | |
return fns.reduce((val, fn) => fn(val), value); | |
} | |
const pipeFlowConst = (value: unknown, ...fns: AnyFn[]): unknown => | |
flow(...fns as Parameters<typeof flow>)(value); | |
function pipeFlowFn(value: unknown, ...fns: AnyFn[]): unknown { | |
return flow(...fns as Parameters<typeof flow>)(value); | |
} | |
const pipeFlowConstConst = (value: unknown, ...fns: AnyFn[]): unknown => | |
flowConst(...fns as Parameters<typeof flowConst>)(value); | |
function pipeFlowConstFn(value: unknown, ...fns: AnyFn[]): unknown { | |
return flowConst(...fns as Parameters<typeof flowConst>)(value); | |
} | |
Deno.bench("flowOptimized", { group: "flow" }, () => { | |
flow(add)(3); | |
flow(add, add)(3); | |
flow(add, add, add)(3); | |
flow(add, add, add, add)(3); | |
flow(add, add, add, add, add)(3); | |
flow(add, add, add, add, add, add)(3); | |
flow(add, add, add, add, add, add, add)(3); | |
flow(add, add, add, add, add, add, add, add)(3); | |
flow(add, add, add, add, add, add, add, add, add)(3); | |
flow(add, add, add, add, add, add, add, add, add, add)(3); | |
flow(add, add, add, add, add, add, add, add, add, add, add)(3); | |
}); | |
Deno.bench("flowReduceConst", { group: "flow" }, () => { | |
flowConst(add)(3); | |
flowConst(add, add)(3); | |
flowConst(add, add, add)(3); | |
flowConst(add, add, add, add)(3); | |
flowConst(add, add, add, add, add)(3); | |
flowConst(add, add, add, add, add, add)(3); | |
flowConst(add, add, add, add, add, add, add)(3); | |
flowConst(add, add, add, add, add, add, add, add)(3); | |
flowConst(add, add, add, add, add, add, add, add, add)(3); | |
flowConst(add, add, add, add, add, add, add, add, add, add)(3); | |
flowConst(add, add, add, add, add, add, add, add, add, add, add)(3); | |
}); | |
Deno.bench("flowReduceFunction", { group: "flow" }, () => { | |
flowFn(add)(3); | |
flowFn(add, add)(3); | |
flowFn(add, add, add)(3); | |
flowFn(add, add, add, add)(3); | |
flowFn(add, add, add, add, add)(3); | |
flowFn(add, add, add, add, add, add)(3); | |
flowFn(add, add, add, add, add, add, add)(3); | |
flowFn(add, add, add, add, add, add, add, add)(3); | |
flowFn(add, add, add, add, add, add, add, add, add)(3); | |
flowFn(add, add, add, add, add, add, add, add, add, add)(3); | |
flowFn(add, add, add, add, add, add, add, add, add, add, add)(3); | |
}); | |
Deno.bench("pipeOptimized", { group: "pipe" }, () => { | |
pipe(3, add); | |
pipe(3, add, add); | |
pipe(3, add, add, add); | |
pipe(3, add, add, add, add); | |
pipe(3, add, add, add, add, add); | |
pipe(3, add, add, add, add, add, add); | |
pipe(3, add, add, add, add, add, add, add); | |
pipe(3, add, add, add, add, add, add, add, add); | |
pipe(3, add, add, add, add, add, add, add, add, add); | |
pipe(3, add, add, add, add, add, add, add, add, add, add); | |
pipe(3, add, add, add, add, add, add, add, add, add, add, add); | |
}); | |
Deno.bench("pipeReduceConst", { group: "pipe" }, () => { | |
pipeConst(3, add); | |
pipeConst(3, add, add); | |
pipeConst(3, add, add, add); | |
pipeConst(3, add, add, add, add); | |
pipeConst(3, add, add, add, add, add); | |
pipeConst(3, add, add, add, add, add, add); | |
pipeConst(3, add, add, add, add, add, add, add); | |
pipeConst(3, add, add, add, add, add, add, add, add); | |
pipeConst(3, add, add, add, add, add, add, add, add, add); | |
pipeConst(3, add, add, add, add, add, add, add, add, add, add); | |
pipeConst(3, add, add, add, add, add, add, add, add, add, add, add); | |
}); | |
Deno.bench("pipeReduceFunction", { group: "pipe" }, () => { | |
pipeFn(3, add); | |
pipeFn(3, add, add); | |
pipeFn(3, add, add, add); | |
pipeFn(3, add, add, add, add); | |
pipeFn(3, add, add, add, add, add); | |
pipeFn(3, add, add, add, add, add, add); | |
pipeFn(3, add, add, add, add, add, add, add); | |
pipeFn(3, add, add, add, add, add, add, add, add); | |
pipeFn(3, add, add, add, add, add, add, add, add, add); | |
pipeFn(3, add, add, add, add, add, add, add, add, add, add); | |
pipeFn(3, add, add, add, add, add, add, add, add, add, add, add); | |
}); | |
Deno.bench("pipeFlowConst", { group: "pipe" }, () => { | |
pipeFlowConst(3, add); | |
pipeFlowConst(3, add, add); | |
pipeFlowConst(3, add, add, add); | |
pipeFlowConst(3, add, add, add, add); | |
pipeFlowConst(3, add, add, add, add, add); | |
pipeFlowConst(3, add, add, add, add, add, add); | |
pipeFlowConst(3, add, add, add, add, add, add, add); | |
pipeFlowConst(3, add, add, add, add, add, add, add, add); | |
pipeFlowConst(3, add, add, add, add, add, add, add, add, add); | |
pipeFlowConst(3, add, add, add, add, add, add, add, add, add, add); | |
pipeFlowConst(3, add, add, add, add, add, add, add, add, add, add, add); | |
}); | |
Deno.bench("pipeFlowFunction", { group: "pipe" }, () => { | |
pipeFlowFn(3, add); | |
pipeFlowFn(3, add, add); | |
pipeFlowFn(3, add, add, add); | |
pipeFlowFn(3, add, add, add, add); | |
pipeFlowFn(3, add, add, add, add, add); | |
pipeFlowFn(3, add, add, add, add, add, add); | |
pipeFlowFn(3, add, add, add, add, add, add, add); | |
pipeFlowFn(3, add, add, add, add, add, add, add, add); | |
pipeFlowFn(3, add, add, add, add, add, add, add, add, add); | |
pipeFlowFn(3, add, add, add, add, add, add, add, add, add, add); | |
pipeFlowFn(3, add, add, add, add, add, add, add, add, add, add, add); | |
}); | |
Deno.bench("pipeFlowConstConst", { group: "pipe" }, () => { | |
pipeFlowConstConst(3, add); | |
pipeFlowConstConst(3, add, add); | |
pipeFlowConstConst(3, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add, add, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add, add, add, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add, add, add, add, add, add, add); | |
pipeFlowConstConst(3, add, add, add, add, add, add, add, add, add, add, add); | |
}); | |
Deno.bench("pipeFlowConstFunction", { group: "pipe" }, () => { | |
pipeFlowConstFn(3, add); | |
pipeFlowConstFn(3, add, add); | |
pipeFlowConstFn(3, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add, add, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add, add, add, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add, add, add, add, add, add, add); | |
pipeFlowConstFn(3, add, add, add, add, add, add, add, add, add, add, add); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
These benchmarks don't do enough work to actually measure anything..