At different levels you might optimize your JavaScript code. Sometimes optimization is a matter of good practices such as avoid using logging in loops.
This is not a holy bible, it’s just a guide with some tips that can be implemented in your projects or not. There’s not recipes, just good practices.
Most of these tips also can be applied also to other programming languages
console.log('My variable value is: '+myVar);
As a thumb rule for logging is to avoid printing them in loops. So, avoid deploy code to production like this one:
for(let i = 0; 1 < 10; i++){
console.info('I am '+i);
}
console.time('myQuery');
//execute query
console.timeEnd('myQuery');
The above code will print:
myQuery: 2398ms
// bad
async function getUserInfo(id) {
const profile = await getUserProfile(id);
const repo = await getUserRepo(id)
return { profile, repo }
}
// good
async function getUserInfo(id) {
const [profile, repo] = await Promise.all([
getUserProfile(id),
getUserRepo(id)
])
return { profile, repo }
}
return new Promise((resolve, reject) => {
//my heavy operation
return 'something';
});
This way the code runs in a separate thread, different than the Event Loop
return Promise.resolve().then(() => {
//my heavy operation
return 'something';
});
Some benchmark of this
const size = 1000 * 1000 * 100;
const array = new Array(size);
function doSomethingHeavy() {
let i = 0;
while(i < array.length){
i++;
}
}
function doSomethingHeavyWithPromise(){
return new Promise(function(resolve, reject){
doSomethingHeavy();
return 'done with promise';
});
}
function doSomethingHeavyWithEnhancedPromise(){
return Promise.resolve().then(function(value){
doSomethingHeavy();
return 'done with enhanced promise';
});
}
console.time('promise');
doSomethingHeavyWithPromise().then(function(result){
console.info(result);
});
console.timeEnd('promise');
//prints: promise: 69.772ms (It's using the main thread blocking the event loop! )
console.time('enhancedPromise');
doSomethingHeavyWithEnhancedPromise()
.then(function(result){
console.info(result);
});
console.timeEnd('enhancedPromise');
//prints enhancedPromise: 0.135ms (it uses a separate thread leaving the event loop free for other requests)
const size = 1000 * 1000 * 10;
const array = new Array(size);
function doSomething() {
let i = 0;
i++;
}
console.time("classicForWithLength");
for (let i = 0; i < array.length; i++) {
doSomething();
}
console.timeEnd("classicForWithLength");
console.time("classicForWithSize");
for (let i = 0; i < size; i++) {
doSomething();
}
console.timeEnd("classicForWithSize");
console.time("forEach");
array.forEach(element => {
doSomething();
});
console.timeEnd("forEach");
console.time("forIn");
for (let e in array) {
doSomething();
}
console.timeEnd("forIn");
console.time("forOf");
for (let e of array) {
doSomething();
}
console.timeEnd("forOf");
console.time("forEachWithFunction");
array.forEach(function(item, index, object) {
doSomething();
});
console.timeEnd("forEachWithFunction");
console.time("forEachWithArrow");
array.forEach((item, index, object) => {
doSomething();
});
console.timeEnd("forEachWithArrow");
The output of this script:
classicForWithLength: 21.604ms
classicForWithSize: 11.532ms
forEach: 32.330ms
forIn: 59.182ms
forOf: 185.412ms
forEachWithFunction: 32.033ms
forEachWithArrow: 32.564ms
Interesting conclusions we might write:
The fastest is the classicfor
sentence
i < constantValue
is better than i < myCollection.length
So you should use the classic for when iterating big collections! Tools Luckily we have a lot of awesome tools to make some benchmark such as jMeter o Artillery. They are used mostly to make web services load test.