Skip to content

Instantly share code, notes, and snippets.

@baetheus
Created December 31, 2022 01:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save baetheus/ec8b243a6b52175bfc1dc5a6532355ec to your computer and use it in GitHub Desktop.
Save baetheus/ec8b243a6b52175bfc1dc5a6532355ec to your computer and use it in GitHub Desktop.
Pipe and Flow benchmarks
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
//
// 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);
});
@baetheus
Copy link
Author

These benchmarks don't do enough work to actually measure anything..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment