Quick and Easy JavaScript Benchmarking

Daniel Lempesis
5 min readJun 25, 2018

--

A quick note: Different browsers will achieve different results even on the same machines. It is completely possible for a piece of code to perform faster on Firefox Quantum than on Google Chrome, or for Opera to lag behind Safari on one task while outpacing it on another. (The same holds true for mobile browsing across iOS and Android.) The only true constant when it comes to comparing results across platforms is comparing the results of any other browser to that of Internet Explorer; regardless of how slow it is on your browser, it beats not working at all.

JSPerf is great. You can compare many different code snippets at once and view the results right next to each other in a very readable format, save and even share your results, all while keeping track of exactly what version of each browser you used to do so. It even handles asynchronous JavaScript. But making little tweaks to the code can be annoying — you have to reload the entire page, save it again, wait for the page to load, and then wait a fair amount of time for all results to finish. The site also isn’t always stable or accessible, and while it’s convenient to be able to log in with GitHub, you often get logged out, and sometimes the site is slow.

So, JSPerf is a great tool for stable JavaScript benchmarking. If you’re looking for something quick and easy, however, look no further than your Chrome (or Firefox) console.

Mozilla and Google, the companies responsible for the world’s two most popular desktop browsers, have gone out of their way to offer convenient, highly-usable consoles that you can work in. Just hit option + command + J (ctrl + shift + J on Windows), and you’re ready to go.

new Date generates a date-time stamp for you: Fri Jun 22 2018 16:54:38 GMT-0400 (Eastern Daylight Time) It also offers a convenient feature that lends itself nicely to doing a little benchmarking: If you subtract one time from another after performing some sort of operation, you get a time in milliseconds. Side-note: You can also use performance.now() in lieu of new Date(). It’s got a higher granularity and may give more consistent results. You probably don’t need it though.

For example, say you’re interested in benchmarking code you wrote to determine the sum of the multiples of 3 and 5 below n against other people’s solutions:

const mySolution = n => {
let sum = 0

for (let i = 0; i < n; i++)
if (i % 3 === 0 || i % 5 === 0)
sum += i
return sum
}

vs.

const otherSolution = n => {
let number = n-1;
const fives = Math.floor(number/5) // # of multiples of 5 below n
, threes = Math.floor(number/3)
, fifteens = Math.floor(number/15)
, sum = (base, num) => base * (num ** 2 + num)/2;
return sum(5, fives) + sum(3, threes) - sum(15, fifteens)
};

Let’s try it.

let then = new Date;for (let i = 0; i < 1000; i++) {
mySolution(100000);
}
let now = new Date;now - then;
This is what we get

That was easy. We created a new date before starting our loop, performed our function 1000 times with our solution where n = 100000, then created a new date after it completed and subtracted the current time from the start time. In this case, we got 396ms.

Let’s benchmark the other one now.

then = new Date //then and now were already declared
for (let i = 0; i < 1000; i++) {
otherSolution(100000)
}
now = new Date
now - then
The other solution. It’s a bit faster.

Hmm. Looks like theirs is a bit faster. Exactly how much faster though it’s not possible to say. We need to bump the number of iterations we’re doing (given that this is an O(1) solution, increasing the size of the input won’t really increase runtime).

Still not perfect, but good enough to give us a good picture. We’ve increased the number of operations 10,000 fold, and hit 17ms. This solution is around 233,000 times faster, at least for this input (the original solution is of O(n) complexity, so it should scale fairly linearly).

And that’s basically all there is to it. If you want to benchmark different parts of your code, you can console.log out start-end times in different parts of your code. This should work for asynchronous JavaScript as well. It’s certainly not as full-featured as something like JSPerf, but it’s quick, you can make easy changes, and you can control the number of iterations.

Additional Tip:

You might get tired of writing all of this out over and over (or at least continually hitting the up arrow and modifying the code you just ran). You can wrap all of this up in a convenient, reusable function like this:

const bench = (func, input, iterations) => {
/* any boilerplate code you want to have happen before the timer starts, perhaps copying a variable so it isn't mutated */
const start = new Date; for (let i = 0; i < iterations; i++) {
func(input)
}
const finish = new Date return (finish - start)
}

We can now call our function quickly and easily to benchmark our code with minimal setup. Just invoke as bench(functionName, input, numIterations)!

Now go forth! Benchmark to your heart’s content! Just remember to use a large enough data set and enough testing iterations to get meaningful results. :)

--

--