31 Aug 2013

JavaScript Performance Tips

Some say spending time developing for performance is not worth it when hardware upgrades are usually a cheaper alternative. If I would tell them that spending 10 minutes reading this could save more than 50 new upgrades with simple code improvements that account for a 50x+ performance increase, do you think they would listen?
From rarely used and almost forbidden code snippets to commonly used methods and loops, I am about to show how to cut unnecessary milliseconds out of your JavaScript application.
All tests are measured in ops/sec (higher is better), the widely known jsperf.com benchmarking style. In fact, benchmark.js was used to conduct the tests cross-browser. The tests were conducted on a 2011 MacBook Pro, 2.2 GHz i7 processor with 8GB RAM and a Vertex 3 SSD, all running on a 10.7.4 OS X Lion or Windows XP SP3 through Parallels 7.

Evaluation

I can hear you saying “Oh but Crockford says eval is evil and I agree with him.” I concur, but there are cases when evaluation is important, such as:
  • Code caching. Sometimes we choose to cache parts of our apps in the browser through one of the available web storage mechanisms.
  • Deferred execution. On mobile devices, JavaScript execution takes approximately1ms for each 1kB of code.
  • Loading on demand. Some architects choose to load application modules on demand to save on bandwidth and increase security measures.
eval() is the function available in JavaScript that is meant to be used for code evaluation. It accepts a string that should represent a section of code, properly formatted.
Let’s examine the following code:
var str = "",
    i = 0;
for (; i<1000; i += 1) {
    str += "a";
}
This simple loop appends a character to a string. Strings are immutable in JavaScript, thus str will be overwritten with each change. Now, let’s change the code into a eval-compatible string.
var strCode = 'var str="",i=0;for(;i<1000 a="" i="" span="" str="">;
Ugly. Benchmarking eval(strCode) on Chrome 21 will output 97 ops/sec. Make sure you make a mental note here.
Alternatively, let’s do the same thing, but this time we will evaluate using a little trick:
(new Function(strCode))()
Benchmarking this snippet in the same browser will output 5,256 ops/sec, a staggering54.2x (or 5,418%) speed increase.
JavaScript Evaluation vs (new Function())()
Google Chrome’s V8 engine is to ‘blame’ for such performance. Unfortunately or luckily, depending on how you look at it, not all browsers use V8. However, all browsers consistently report performance benefits with the latter approach, whether they are by as much as 5400% or 10% (IE6).

No comments:

Post a Comment