Performance Guide for Tizen Web Applications(3): Coding Tips

Coding Tips for Performance-driven Development

This section gives tips for handling code performance-effectively.

 

1 Variables and Literals

 

  • Defining Local Variables

When a variable is referenced, the JavaScript engine locates it by looping through the different members of the scope chain. This scope chain is the set of variables available within the current scope, and across all major browsers it has at least two items: a set of local variables and a set of global variables. In short, the deeper the engine has to dig into this scope chain, the longer the operation takes.

The engine first goes through the local variables starting with this, the function arguments, then any locally defined variables, and afterwards iterates through any global variables. Since local variables are first in the chain, they are always faster than global variables. Therefore, anytime you use a global variable more than once, consider redefining it as a local variable [7].

The following example shows how to change a global variable to a local one:

var a = document.getElementById("aaa");
var b = document.getElementById("bbb");
var doc = document; // document is defined to local variables
var a = doc.getElementById("aaa"),
    b = doc.getElementById("bbb");

 

  • Caching Repeatedly Used Objects

Caching an object that is repeatedly accessed can boost your JavaScript performance. You can save the lookup cost by storing the object inside a custom variable, and using the variable instead of the object in subsequent references to that object.

The following example shows how to cache an object into a custom variable:

for (i=0;i<document.images.length;i++)
   document.images[i].src="test.gif”   
var imgs=document.images,
img_len=imgs.length;

for (i=0;i< img_len;i++)
     imgs[i].src="test.gif”

 

  • Using the Single var Pattern

The JavaScript engine hosts all the variables at the top of a function. Even if you declare a variable at the bottom of the function, the engine still hosts it at the top. Therefore, it is recommended that you declare all variables at the beginning of a function with a single var statement [8].

The following example shows how to rewrite multiple variable declarations across a function as a single combined declaration at the top of the function:

function foo() {
    var c = 1;
    …
    …
    var d = 0;
    var e;
}
function foo() {
    var c = 1, d = 0, e;
    …
    …
    …
}

 

  • Cleaning Up After Using Objects

To avoid memory leaks, delete objects immediately after using them. Do not wait for garbage collection.

 

2 Flow Control: Loops, Conditionals, and with()

 

  • Avoiding for-in Loops (and Function-based Iteration) [7]

The logic behind a for-in loop is straightforward: instead of looping through a set of indexes, a for-in loop loops through the properties of an object, such as the items of an array, which requires more effort. To loop through the properties, JavaScript has to set up a function for each property. This function-based iteration comes with a slew of performance issues: an extra function is introduced with a corresponding execution context that is created and destroyed, on top of which an additional object is added to the scope chain.

The following example shows how to rewrite a for-in loop as a normal for loop:

var i, c;
for (i in c=[1,2,3]) {
    console.log(c[i]);
}
var i, c = [1,2,3],
    len = c.length, i;
    
for (i = 0; i<len; i++) {
    console.log(c[i]);
}

 

  • Using the Proper Type of Conditional

JavaScript supports several types of conditionals. For the best performance, it is important that you use the proper type for each use case [9]. The following examples describe 3 types of conditionals: the if statement, the switch statement, and the array lookup. Each type has its uses in optimizing code execution.

Use the if statement when:

  • There are no more than 2 discrete values for which to test.
  • There are a large number of values that can be easily separated into ranges.
if (value < 0)  {
    return “positive”;
} else {
    return “negative”;
}

 

Use the switch statement when:

  • There are more than 2 but fewer than 10 discrete values for which to test.
  • There are no ranges for conditions because the values are nonlinear.
switch(value){
    case 0:
        return “0”;
    case 1:
        return “1”;
    case 2:
        return “2”;
    default:
        return  “default”;
}

 

Use the array lookup when:

  • There are more than 10 values for which to test.
  • The results of the conditions are single values rather than a number of actions to be taken.
function num_range (num) {
    var arr_range = [“~10”, “11~20”, “21~30”, “31~40”, “41~50”, “51~60”, “61~70”, “71~80”, “81~90”, “91~100”],
        idx = Math.ceil(num/10) -1,
        arr_len=arr_range.lengh;
            
    if (idx<0) 
        console.log(“range:”, range[0]);
    else if (idx >= arr_len)
        console.log(“range:”, range[arr_len -1]);
    else 
        console.log(“range:”, range[idx]); 
}

 

  • Avoiding with() statements

The with() statement modifies the scope chain by adding an extra set of variables to the beginning of the chain. Because of these added variables, to access a specific variable, the JavaScript engine has to loop through the with() variables, the local variables, and the global variables. In short, the with() statement gives local variables all the performance drawbacks of global variables, which in turn compromises JavaScript optimization.

var exam = {subject: “math”, score: “86”}

with (exam) 
{
    console.log(subject);
    console.log(score);
}
var exam = {subject: “math”, score: “86”}

console.log(exam.subject);
console.log(exam.score);

 

  • Reversing Loop Order

You can increase the performance of loops by reversing their order. In JavaScript, reversing a loop results in a small performance improvement provided that you eliminate any extra operations. [10]

The following example shows how to loop in reverse order:

var i, 
j = items.length,
    k= items.lengh-1;
for (; i-- ; ) {
   //do something
}

while(j--) {
    //do something
}
    
do {
    //do something 
} while (k--);

 

3 Functions and Closures

 

  • Using Closures Sparingly

Closures are a powerful and useful aspect of JavaScript, but they come with their own performance drawbacks. Basically, a closure can be thought of as the new operator in JavaScript, and you use one whenever you define a function on the fly.

The problem with closures is that, by definition, they have a minimum of 3 objects in their scope chain: the closure variables, the local variables, and the global variables. These extra items lead to performance problems. Therefore, do not overuse closures, especially inside loops [7].

The following example shows how to remove a closure from a loop:

for (var i = 0; i < 100; i++)
{
    var test  = function() 
    {
        console.log(“Call #”, i);
    }
}
function exFn(idx) 
{
    console.log(“Call #”, idx);
} 
for (var i = 0; i < 100; i++) 
{
    exFn(i);
}

 

  • Avoiding Nesting Deep Inside a Function

Avoid nesting deep within a function [9].

The following example shows how to removing deep nesting from a function:

function successCbk(r) 
{
    if (r) 
    {
        if (r.data) 
        {
            if (r.data.myProp) 
            {
                …
            } else {
                …
            }
        }
    }
}
function successCbk(r) 
{
    if (!r) return;
    if (!r.data) return;
    
    if (r.data.myProp) 
    {
        …
    } else {
        …
    }
}

 

 

References

[1] Performance Guide for Web App: http://www.samsungdforum.com/Guide/d60/index.html

[2] Best Practices for Speeding Up Your Web Site: https://developer.yahoo.com/performance/rules.html

[3] Web workers: http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html#workers

[4] Minify Resources (HTML, CSS, and JavaScript): https://developers.google.com/speed/docs/insights/MinifyResources

[5] Notes on HTML Reflow: http://www-archive.mozilla.org/newlayout/doc/reflow.html

[6] Minimizing browser reflow: https://developers.google.com/speed/articles/reflow

[7] 10 JavaScript Performance Boosting Tips from Nicholas Zakas: http://jonraasch.com/blog/10-javascript-performance-boosting-tips-from-nicholas-zakas

[8] JavaScript Performance Tips, http://www.codeproject.com/Tips/623082/JavaScript-Performance-Tips

[9] Writing Efficient JavaScript: Chapter 7 - Even Faster Websites, http://archive.oreilly.com/pub/a/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html

[10] High Performance JavaScript, Nicholas C. Zakas