Transducer and latest nodejs (>= 10) can sing faster duet
October 19, 2019
Prerequisite
Need some basic understanding of
I will also link more interesting articles about functional programming and transducers in the end.
Excercise
Now run the following code-which is in nutshell, just filter registered users and sum up the total discount from the given millions of users(array) in 3 different ways-against nodejs versions 8, 9, 10, 12
const { map, filter, compose, transduce } = require('ramda');
// utils
const timeIt = (label, fn) => {
console.time(label);
fn();
console.timeEnd(label);
};
const getRange = n => [...Array(n).keys()]
// data
const users = getRange(1000000).map((_, index) => ({
registered: index % 2 === 0,
discount: 1,
}))
// helpers
const isRegistered = user => user.registered;
const getDiscount = user => user.discount;
const totalDiscountReducer = (
totalDiscount,
discount
) => totalDiscount + discount;
// efficient way to get total discount
const getTotalDiscountForRegisteredUsersEfficiently = () => {
let totalDiscount = 0;
users.forEach(user => {
if(user.registered) totalDiscount += user.discount;
})
return totalDiscount;
}
// elegant way to get total discount
const getTotalDiscountForRegisteredUsersElegantly = () => users
.filter(isRegistered)
.map(getDiscount)
.reduce(totalDiscountReducer, 0)
const getDiscountForRegisteredUser = compose(
filter(isRegistered),
map(getDiscount)
);
// elegant and efficient way to get total discount
const getTotalDiscountForRegisteredUsers = () => transduce(
getDiscountForRegisteredUser,
totalDiscountReducer,
0,
users
)
timeIt(
'Loop(Efficient)',
getTotalDiscountForRegisteredUsersEfficiently
)
timeIt(
'Chaining(Elegant)',
getTotalDiscountForRegisteredUsersElegantly
)
timeIt(
'Transduce(Efficient and Elegant)',
getTotalDiscountForRegisteredUsers
)
I have prepared runkit link too: https://runkit.com/peramanathan/transducer-simplified
Match your results
- Node 8:
"Loop(Efficient): 25.328ms" "Chaining(Elegant): 247.965ms" "Transduce(Efficient and Elegant): 631.458ms"
- Node 9:
"Loop(Efficient): 21.147ms" "Chaining(Elegant): 154.018ms" "Transduce(Efficient and Elegant): 688.818ms"
- Node 10:
"Loop(Efficient): 17.144ms" "Chaining(Elegant): 106.336ms" "Transduce(Efficient and Elegant): 14.785ms"
- Node 11
"Loop(Efficient): 21.290ms" "Chaining(Elegant): 152.711ms" "Transduce(Efficient and Elegant): 16.327ms"
- Node 12
"Loop(Efficient): 34.232ms" "Chaining(Elegant): 102.873ms" "Transduce(Efficient and Elegant): 11.597ms"