Let’s Write Fast JavaScript

A few interesting JavaScript benchmarks and tips

JavaScript is the most popular language as of now, it’s used for a wide variety of things — creating websites, servers, games, operating systems, robots, and a hell of a lot more.

But let’s be honest, even with it’s crazy popularity, it’s not as fast as it should be. Yes it’s improving, but wait for it to catch up with native everywhere. I mean, it might not be as slow on desktop, but make a hybird application and you’ll have to use hundreds of shitty tricks just to make it usable. I had this experience.

Firefox has the fastest JavaScript interpreter, SpiderMonkey. Check out Are We Fast Yet for a more details and comparisons surrounding different engines and benchmarks.

There are various efforts to make JavaScript faster, one of them is asm.js. Asm.js is a subset of JavaScript which is generated by Emscripten which compiles C/C++ code to JavaScript with a lot of optimizations, compiled codes look ugly, that’s why you can’t write optimized code yourself, but it runs really fast. I really recommend you to check out Alon Zakai’s Big Web App? Compile It! slides. For more in-depth information on asm.js and emscripten I recommend John Resig’s article on this topic.

Shut up and show me the tips!

Alright, so we want to write faster JavaScript code, here are a few small tips on making your code faster, and more memory efficient. Please note, I’m not strictly talking about DOM and web apps, it’s about JavaScript, DOM included.

Seeing is believing, I’m going to add a jsperf test case for every tip, and test it using Firefox 38 and Chrome 39.

Credit: Celesty Lee

#1 Don’t make me typecast

JavaScript is dynamically typed, but try not to use that feature if you want speed. Try to keep variables’ types consistent. It also applies to arrays, try not to mix different types in an array, althought it’s mostly optimized by browsers. That’s one of the reasons why C/C++ code compiled to JavaScript is fast, static types.

Edit: The test case was technically wrong, sorry. I made another test case for mixed-type arrays which I think is a better proof to this. Thanks to Roman Pominov and Matt Perry for mentioning this.

var x = '2';
var y = 5;
x = 2;
x + y;

Test Case

Bonus: String to Number conversion

Let’s say you must convert a string to a number, are parseInt & parseFloat the best ways of doing it? Let’s see.

// Different ways of parsing integer/float from strings
// integer only
parseInt("100", 10)
"100" >> 0
"100" << 0
//Only works for positive numbers
"100" >>> 0

parseInt test ~ parseFloat test

Firefox optimizes it away (see Vyacheslav Egorovs note) bitwise operators, running the code is about 99% faster than parseInt and + operator. But Chrome shows no love for bitwise operators, they’re at best ~62% slower than parseInt.

parseFloat is faster than + operator on both browsers (28% on Firefox, 39% on Chrome).

So it varies on your use case, are you writing Node / Chrome Applications or Firefox Applications? I think for general purpose, parseInt is the right one to use.

#2 Don’t re-structure objects

Re-structuring objects is not cheap, follow these tips to avoid it:

Don’t use delete operator

Delete operator is a lot slower than assigning null to a property. Assigning null is 99% faster on both browsers, because it doesn’t modify an object’s structure, but delete does.

Edit: I think the tip was a little misleading, this doesn’t mean you shouldn’t use delete operator, the delete operator has it’s own use case, and as Arnout Kazemier and Mohammad Jahani mentioned (thanks), it prevents memory leaks in objects, but in case you’re hungry for speed, you can use this tip.

delete vs null

Don’t add properties later

Try not to add properties later, best to define your object’s schema from the beginning. It’s 100% faster on Firefox and 89% faster on Chrome.

dynamic properties vs pre-defined structure

#3 String concatenating

String concatenating is a pretty expensive operation, but what’s the best way of doing it? Certainly not Array.prototype.join.

The results vary between different browsers, I recommend you run the test on different browsers and see the results yourself. To mention the fastest cases: Reassociating strings (kinda like grouping them) is the fastest on Firefox, while using Array.prototype.join, with help of constant fold is the fastest on Chrome. The slowest cases seem to be String.prototype.concat and normal + operator on both browsers.

Edit: Thanks to Vyacheslav Egorov for mentioning my test case’s problems and fixing them, he made a test case which shows more realistic results, his explainations are just awesome, thank you so much. Read his comment in JSPerf test below.

String concatenating

#4 Use The Right RegExp Method

It doesn’t make sense to use RegExp.prototype.exec when you want to test against something, does it?

Yet there are performance differences between RegExp.prototype.test and String.prototype.search, let’s see which methods are faster:

Regex Methods

RegExp.prototype.exec is a lot faster than String.prototype.match, but that’s because they are not exactly the same thing, they are different, their difference is out of this article’s scope, see this question: Stack Overflow.

In searching for existence RegEx.prototype.test is faster, probably because it doesn’t return the index of found match. String.prototype.search should only be used to find the index of desired match.

Yet you should not use RegExps to find specific string’s index inside another string, there’s a method for that, String.prototype.indexOf.

String.prototype.search vs String.prototype.indexOf

Another interesting benchmark is String.prototype.indexOf vs RegExp.prototype.test, I personally expected the latter to be faster, that’s what happens in Firefox, but in Chrome, it’s not. RegExp.prototype.test is 32% faster on Firefox, while String.prototype.indexOf is 33% faster on Chrome. In times like this, go with the one you like most, i think.

#5 Declare & Pass Local Scoped Variables

When you call a function (for example), the browser has to do something called scope lookup, which is expensive based on how many scopes it has to lookup. Try not to rely on global/higher scoped variables, instead, make locally scoped variables and pass them to functions. Fewer scopes to lookup, less speed to sacrifice.

This test shows us that passing variables to functions and using them from local scope is faster than looking up higher scopes to find a variable, both in Chrome and Firefox.

internal scope vs higher scope vs global

#6 You don’t need jQuery for everything

Most developers use jQuery to do the most simple tasks, I mean you don’t have to use jQuery because it’s included in your project, do you think using $val() is always necessary? Take this example:

$('input').keyup(function() {
if($(this).val() === 'blah') { ... }

This is one of the most important reasons to learn how to modify the DOM using vanilla JavaScript, this way you can write more efficient code.

Writing the same condition in vanilla JavaScript is A LOT faster (actually it doesn’t fit in percentages), as proven by this JSPerf Test.

$('input').keyup(function() {
if(this.value === 'blah') { ... }

Bonus Tip: Use Web Workers for Heavy Tasks

If you have heavy calculations in your app, let’s say, some image processing, you’d better use Web Workers to let the browser run the task in a background thread and give you the results asynchronously instead of hanging up and annoying the user.

You can also use the message channels to show the progress of the task, let’s say you have a long for loop (iterating over pixels for example), you can send a message to indicate how much of the loop is done each 100 iterations and show a progress bar so the user knows what’s happening.

That’s it, seven tips and eleven benchmarks to help you write faster JavaScript. It’s not all about performance tricks, it’s about understanding how things work in JavaScript to take your programming skills a level further.

If you found these tips helpful, please recommend and share so others can learn about these tips, too!

Have any suggestions about these tips or just want to say hello? Follow me on Twitter, I’d be glad to have a discussion with you.

Software Engineer at AYLIEN. Opensource guy. Mozillian.


Software Engineer at AYLIEN. Opensource guy. Mozillian.