Skip to content

Instantly share code, notes, and snippets.

@tgroshon
Forked from jcoglan/README.md
Last active May 25, 2021 22:20
Show Gist options
  • Save tgroshon/3ef57a31f7ccb2d7706d7f8645dcd161 to your computer and use it in GitHub Desktop.
Save tgroshon/3ef57a31f7ccb2d7706d7f8645dcd161 to your computer and use it in GitHub Desktop.
JavaScrpit benchmark: reduce, filter, map(), transducers, and for loops

benchmark: reduce(), filter(), map(), transducers and for loops

reduce():            10    x 832,441 ops/sec ±1.11% (87 runs sampled)
reduce():            100   x 56,307 ops/sec ±1.65% (87 runs sampled)
reduce():            1,000 x 1,158 ops/sec ±1.58% (88 runs sampled)

reduce() w/ mutate:  10    x 3,144,202 ops/sec ±1.27% (91 runs sampled)
reduce() w/ mutate:  100   x 556,441 ops/sec ±1.08% (94 runs sampled)
reduce() w/ mutate:  1,000 x 67,205 ops/sec ±0.40% (97 runs sampled)

forEach():           10    x 3,202,435 ops/sec ±0.62% (83 runs sampled)
forEach():           100   x 597,300 ops/sec ±1.24% (91 runs sampled)
forEach():           1,000 x 67,361 ops/sec ±1.08% (91 runs sampled)

filter() & map():    10    x 184,837 ops/sec ±1.18% (89 runs sampled)
filter() & map():    100   x 15,476 ops/sec ±0.60% (96 runs sampled)
filter() & map():    1,000 x 346 ops/sec ±1.18% (88 runs sampled)

filter/map w/ pairs: 10    x 171,885 ops/sec ±0.44% (92 runs sampled)
filter/map w/ pairs: 100   x 13,407 ops/sec ±0.78% (89 runs sampled)
filter/map w/ pairs: 1,000 x 402 ops/sec ±1.36% (85 runs sampled)

fromEntries():       10    x 917,920 ops/sec ±1.34% (87 runs sampled)
fromEntries():       100   x 122,082 ops/sec ±1.01% (84 runs sampled)
fromEntries():       1,000 x 12,402 ops/sec ±1.20% (91 runs sampled)

transducers:         10    x 162,910 ops/sec ±0.84% (92 runs sampled)
transducers:         100   x 12,612 ops/sec ±0.58% (95 runs sampled)
transducers:         1,000 x 420 ops/sec ±0.26% (92 runs sampled)

for-of-loop:         10    x 3,109,700 ops/sec ±1.02% (93 runs sampled)
for-of-loop:         100   x 588,851 ops/sec ±1.10% (91 runs sampled)
for-of-loop:         1,000 x 64,205 ops/sec ±0.79% (86 runs sampled)

for-loop:            10    x 3,229,874 ops/sec ±0.31% (94 runs sampled)
for-loop:            100   x 580,379 ops/sec ±1.30% (92 runs sampled)
for-loop:            1,000 x 69,433 ops/sec ±1.28% (90 runs sampled)
const { Suite } = require("benchmark");
const {
useReduce,
useReduceMutate,
useForEach,
useFilterMap,
useFilterMap2,
useFromEntries,
useTransduce,
useForLoop,
useForOfLoop
} = require("./impls");
console.log("Preparing run...");
function genUsers(n) {
let users = [];
while (n--) users.push({ active: false, id: n, name: `user ${n}` });
return users;
}
let users = {};
for (let n of [10, 100, 1000]) users[n] = genUsers(n);
let suite = new Suite();
suite.add("reduce(): 10", () => useReduce(users[10]));
suite.add("reduce(): 100", () => useReduce(users[100]));
suite.add("reduce(): 1,000", () => useReduce(users[1000]));
suite.add("reduce() w/ mutate: 10", () => useReduceMutate(users[10]));
suite.add("reduce() w/ mutate: 100", () => useReduceMutate(users[100]));
suite.add("reduce() w/ mutate: 1,000", () => useReduceMutate(users[1000]));
suite.add("forEach(): 10", () => useForEach(users[10]));
suite.add("forEach(): 100", () => useForEach(users[100]));
suite.add("forEach(): 1,000", () => useForEach(users[1000]));
suite.add("filter() & map(): 10", () => useFilterMap(users[10]));
suite.add("filter() & map(): 100", () => useFilterMap(users[100]));
suite.add("filter() & map(): 1,000", () => useFilterMap(users[1000]));
suite.add("filter/map w/ pairs: 10", () => useFilterMap2(users[10]));
suite.add("filter/map w/ pairs: 100", () => useFilterMap2(users[100]));
suite.add("filter/map w/ pairs: 1,000", () => useFilterMap2(users[1000]));
suite.add("fromEntries(): 10", () => useFromEntries(users[10]));
suite.add("fromEntries(): 100", () => useFromEntries(users[100]));
suite.add("fromEntries(): 1,000", () => useFromEntries(users[1000]));
suite.add("transducers: 10", () => useTransduce(users[10]));
suite.add("transducers: 100", () => useTransduce(users[100]));
suite.add("transducers: 1,000", () => useTransduce(users[1000]));
suite.add("for-of-loop: 10", () => useForOfLoop(users[10]));
suite.add("for-of-loop: 100", () => useForOfLoop(users[100]));
suite.add("for-of-loop: 1,000", () => useForOfLoop(users[1000]));
suite.add("for-loop: 10", () => useForLoop(users[10]));
suite.add("for-loop: 100", () => useForLoop(users[100]));
suite.add("for-loop: 1,000", () => useForLoop(users[1000]));
suite.on("complete", () => {
suite.forEach(test => console.log(test.toString()));
});
suite.run();
function useReduce(users) {
return users.reduce((acc, curr) => {
if (curr.active) return acc;
else return { ...acc, [curr.id]: curr.name };
}, {});
}
function useReduceMutate(users) {
return users.reduce((acc, curr) => {
if (curr.active) {
return acc;
}
acc[curr.id] = curr.name;
return acc;
}, {});
}
function useForEach(users) {
const result = {};
users.forEach(user => {
if (user.active) {
return;
}
result[user.id] = user.name;
});
return result;
}
function useFilterMap(users) {
return users
.filter(user => !user.active)
.map(user => ({ [user.id]: user.name }))
.reduce((a, b) => Object.assign(a, b), {});
}
function useFilterMap2(users) {
return users
.filter(user => !user.active)
.map(user => [user.id, user.name])
.reduce((a, [id, name]) => Object.assign(a, { [id]: name }), {});
}
function useFromEntries(users) {
return Object.fromEntries(
users.filter(user => !user.active).map(user => [user.id, user.name])
);
}
function useTransduce(users) {
return users.reduce(
compose([
filter(user => !user.active),
map(user => ({ [user.id]: user.name }))
])(assign),
{}
);
}
const map = f => step => (a, c) => step(a, f(c));
const filter = pred => step => (a, c) => (pred(c) ? step(a, c) : a);
const compose = fns => x => fns.reduceRight((y, f) => f(y), x);
const concat = (a, b) => a.concat([b]);
const assign = (a, b) => Object.assign(a, b);
function useForOfLoop(users) {
let result = {};
for (let user of users) {
if (!user.active) result[user.id] = user.name;
}
return result;
}
function useForLoop(users) {
let result = {};
for (let i = 0; i < users.length; i++) {
let user = users[i];
if (!user.active) {
result[user.id] = user.name;
}
}
return result;
}
module.exports = {
useReduce,
useReduceMutate,
useForEach,
useForLoop,
useFilterMap,
useFilterMap2,
useFromEntries,
useTransduce,
useForOfLoop
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment