|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionWhile we develop AJAX applications, we often carelessly ignore giving up bad practices, which cause effects which are not so significantly visible when the site is not so large in volume. But, it’s often severe performance issue when it is the case for sites that make heavy use of AJAX technologies such as Pageflakes, NetVibes etc. There are so many AJAX widgets in one page that little memory leak issues combined may even result the site crash into very nasty “Operation aborted”. There are a lot of WebService calls, lot of iterations among collection so that inefficient coding in a whole lead to make site very heavy, browser eats up a lot of memory, requires very costly CPU cycles, and ultimately causes unsatisfactory user experience. In this article many of such issues will be demonstrated in the context of ASP.NET AJAX. Use more "var"Less use of "var" can result into wrong calculation as well as mistake in logic control. And also JavaScript interpreter finds it hard to determine the scope of the variable if var is not used. Consider the following simple JavaScript code: function pageLoad()
{
i = 10;
loop();
alert(i); // here, i = 100
}
function loop()
{
for(i=0; i<100; ++i)
{
// Some actions
}
}
Here you see, the loop uses the variable function pageLoad()
{
var i = 10;
loop();
alert(i); // here, i = 10
}
function loop()
{
for(var i=0; i<100; ++i)
{
// Some actions
}
}
Reduce scopesIt’s not pretty common. But, if you ever encounter such code, be sure it’s a very bad practice. Introducing more scopes is a performance issue for JavaScript interpreter. It adds a new scope in the ladder. See the following sample scope: function pageLoad()
{
scope1();
function scope1()
{
alert(’scope1');
scope2();
function scope2()
{
alert(’scope2');
}
}
}
Introducing more scopes enforces the interpreter to go through new more sections in the scope chain that it maintains for code execution. So, unnecessary scopes reduce performance and it’s a bad design too. Careful with DOM element concatenationIt’s a very common bad practice. We often iterate through array, build HTML contents and keep on concatenating into certain DOM element. Every time you execute the block of code under the loop, you create the HTML markups, discover a div, access the function pageLoad()
{
var links = ["microsoft.com", "tanzimsaqib.com", "asp.net"];
$get(‘divContent’).innerHTML = ‘My favorite sites:<br />’
for(var i=0; i<links.length; ++i)
$get(‘divContent’).innerHTML += ‘<a href="http://www.’
+ links[i] + ‘">http://www.’ + links[i] + ‘</a><br />’;
}
However, as you know accessing DOM element is one the costliest operation in JavaScript. So, it’s wise to concatenate all HTML contents in a string and finally assign to the DOM element. That saves a lot of hard work for the browser. function pageLoad()
{
var links = ["microsoft.com", "tanzimsaqib.com", "asp.net"];
var content = ‘My favorite sites:<br />’
for(var i=0; i<links.length; ++i)
content += ‘<a href="http://www.’ + links[i]
+ ‘">http://www.’ + links[i] + ‘</a><br />’;
$get(‘divContent’).innerHTML = content;
}
Avoid using your own method while there is oneAvoid implementing your own Avoid using Array.length in a loopIt's a very common, yet performance issue in AJAX. We often use code like the following: var items = []; // Suppose a very long array
for(var i=0; i<items.length; ++i)
; // Some actions
It can be a severe performance issue if the array is so large. JavaScript is an interpreted language, so when interpreter executes code line by line, every time it checks the condition inside the loop, you end up accessing the length property every time. Wherever it can be applicable, if the contents of the array does not need to be changed during the loop’s execution, there is no necessity to access the length property every time. Take out the length in a variable and use in every iteration: var items = []; // Suppose a very long array
var count = items.length;
for(var i=0; i<count; ++i)
; // Some actions
Avoid String concatenation, use Array insteadDon't you think the following block of code has written keeping every possible good practice in mind? Any option for performance improvement? function pageLoad()
{
var stringArray = new Array();
// Suppose there're a lot of strings in the array like:
stringArray.push('<div>');
stringArray.push('some content');
stringArray.push('</div>');
// ... code edited to save space
var veryLongHtml = $get('divContent').innerHTML;
var count = stringArray.length;
for(var i=0; i<count; ++i)
veryLongHtml += stringArray[i];
}
Well, as you see the veryLongHtml = veryLongHtml + stringArray[i];
And the veryLongHtml contains quite a large string which means in this operation the interpreter will have to retrieve the large string and then concatenate with the stringArray elements in every iteration. One very short yet efficient solution to this problem is using join method of the array like the following, instead of looping through the array: veryLongHtml = stringArray.join('');
However, this is very efficient than the one we were doing, since it joins the array with smaller strings which requires less memory. Introduce function delegatesTake a look at the following loop. This loop calls a function in each iteration and the function does some stuffs. Can you think of any performance improvement idea? for(var i=0; i<count; ++i)
processElement(elements[i]);
Well, for sufficiently large array, function delegates may result in significant performance improvement to the loop. var delegate = processElement;
for(var i=0; i<count; ++i)
delegate(elements[i]);
The reason behind performance improvement is, JavaScript interpreter will use the function as local variable and will not lookup in its scope chain for the function body in each iteration. Introduce DOM elements and function cachingWe have seen DOM caching before and function delegation is also a kind of function caching. Take a look at the following snippet: for(var i=0; i<count; ++i)
$get('divContent').appendChild(elements[i]);
As you can figure out the code is going to be something like: var divContent = $get('divContent');
for(var i=0; i<count; ++i)
divContent.appendChild(elements[i]);
That is fine, but you can also cache browser function like var divContentAppendChild = $get('divContent').appendChild;
for(var i=0; i<count; ++i)
divContentAppendChild(elements[i]);
Problem with switchUnlike .NET languages or any other compiler languages, JavaScript interpreter can not optimize switch block. Especially when switch statement is used with different types of data, it's a heavy operation for the browser due to conversion operations occur in consequences, it's an elegant way of decision branching though. ConclusionIn this article, we have seen many techniques of performance optimization in AJAX application and of course these are not new and unique ideas, so you might find similar ideas else where as well.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||