Table of contents
What kind of comparison is this
I know comparisons should be done between two functions if they complete the same task but in two different ways. But hear me out for a second. Imagine, for some reason, you need to do many console.log()
s on the production release of your app. Or maybe you forgot to remove that console.log("is this working?")
inside a loop that may run so many times. Can you guess how much impact it'll have on your app compared to a return
statement?
How much?
Don't be so lazy. Come on, guess something. Give me a number. How much slower/faster console.log()
will be compared to the return
statement? Okay, I'll give you a hint. It's slower. But how much? 2 times? 3 times? 4 times?
In a test case, I found console.log()
is around 300x SLOWER than return
. Yes. THREE FACKING HUNDRED
Cannot believe that? Check the below screenshot
I know it's only for a single run. Wanna guess what the number will be for 10 runs?
Check below...
The number drastically dropped, right? Like from nearly 300 to directly 61. Yeah, I give you that. Maybe it'll drop to around 6-7 for 100 runs? RIGHT? Not really...
This time we got around 40. Not a big drop like the last one, and also not a small number, when we talk about completion time.
The Table
As we have come so long, let's look at some more numbers in a more structured way. Maybe a table.
Runs | Slower |
1 | 299x |
10 | 61.1x |
100 | 39.74x |
1000 | 42.475x |
10000 | 63.2221x |
100000 | 57.96388x |
1000000 | 56.139433x |
Do you see something? Even for the highest number of runs, console.log()
is still around 55x slower then return
.
The Code
Now the biggest question is, where did I get this number? Well, I wrote a simple script to benchmark these two statements. In case you wanna check those, here it is
function logIt(string: string): void {
console.log(string);
}
function returnIt(string: string): string {
return string;
}
In the above script, I made two simple functions. One is for logging out a string and another one just returns a string.
function performanceCheck(func: Function, name?: string) {
return function (...arg: any[]) {
const start = performance.now();
func(...arg);
const end = performance.now();
const takenTime = end - start;
/*
Uncomment the below line to check
which function took how much time
*/
// console.log(`${name} took: ${takenTime}ms`);
return takenTime;
};
}
Then I wrote the above performanceCheck
function that takes two arguments. The first argument is the actual function that we'll run, and the second optional argument is the name of the function, that we can use to check which function took how much time to complete, by measuring the before and after values of performance.now()
We can use this performanceCheck
function to easily run our main two functions logIt
and returnIt
. Below is the use case
function runningTheTest(times: number) {
const resultArray: number[] = [];
const text = " logging it";
for (let _i = 0; _i < times; _i++) {
const performanceParam_log = performanceCheck(logIt, "console.log()");
const performanceParam_return = performanceCheck(returnIt, "return");
const result = (
performanceParam_log(text) / performanceParam_return(text)
).toFixed();
resultArray.push(Number(result));
/*
Uncomment the below line to check
which run was how many times faster.
i.e. `run_123 ==> 20x faster`
*/
// console.log(`\nrun_${_i + 1} ==> ${result}x faster\n`);
}
let total = 0;
for (let _i = 0; _i < resultArray.length; _i++) {
const result_element = resultArray[_i];
total += result_element;
}
const average = total / times;
console.log(`\n return is ${average}x faster then console.log() on average`);
console.log(` In ${times} run(s)\n`);
}
Quite a long function we have now. Don't worry. Let's break it down.
As the name suggests, this function will run the tests a number of times. How many times? Well, as it takes a times
parameter, we can pass that dynamically to the function. Then it declares an empty array to store all the results, which we can use later to calculate an average.
Then we start a for
loop that runs "times"
times and increases the value of _i
by 1 on each run. Inside this loop, is the actual code that'll do our test.
Inside the loop, I'm calling the performanceCheck
function twice. One for console.log()
and one for the return
statement. Notice that while calling the performanceCheck
function, the second parameter I'm passing is the name of the function. Then after getting the corresponding returned values in performanceParam_log
and performanceParam_return
variable, I'm calculating a result
. Notice that, performanceParam_log
and performanceParam_return
aren't value actual value. If we look at the performanceCheck
function, it doesn't return any value. It returns a function that we can call with the necessary parameters. So as the logic goes, I'm calculating result
by dividing the returned value of performanceParam_log
and performanceParam_return
. I'm also using the toFixed
function to round up the value to a fixed number of integers after the dot(.) to reduce confusion.
And we're pretty much done here. We now just need to store the result
value in the resultArray
to calculate the average later (We need to store it as integers to do the math).
After all this, the only left thing is the average calculating part. Which relatively an easy job to do. We just need to declare a variable with the value of 0 to store the sum. We can name it as total
. Then we just keep adding the elements of resultArray
to total
one by one.
After getting the total of all elements in resultArray
We can calculate the average by dividing total
with times
or the length of resultArray
.
Conclusion
So how this knowledge will help us?
Just as I started, in case you need to do so many console.log()
in your production release, or a log inside a loop; don't do it directly. store all the values in a variable that you wanna log, and then just console.log()
that variable once