jQuery Add Elements Dynamically: Performance Tip

jQuery provides several ways of adding elements dynamically into an already existing element. Some methods are: before(), insertBefore() after(), insertAfter(), append, appendTo, prepend, prependTo and so on.

A couple of days ago, I had shared a tip on how jQuery Event Delegation Improves Performance. In this short article, I will share a quick performance tip while using jQuery.append() which inserts content at the end of the interior of each matched element.

Here’s a basic piece of code that appends a new paragraph element into a div (container). We are assuming that the content to be inserted has been fetched dynamically.

$('.container').append('<p>Lorem ipsum dolor sit amet</p>');

Now this code works good if the number of elements to be inserted were few. But let’s say if were to insert hundreds on new elements using jQuery append, how will this piece of code perform? Let’s first see what developers usually tend to do while inserting a large of elements and how it impacts performance.

First let’s declare some HTML with an existing container element and to display the time taken while adding new elements to this container element

html elements

Now when generating a number of elements on the fly, developers usually tend to write a loop and drop this code inside the loop.

var start = new Date().getTime();
for(var cnt=0; cnt < 200; cnt++){
         $('.container').append('<p>Lorem ipsum dolor sit amet</p>');
}

var timeElapsed = new Date().getTime() - start;
$('#timetaken').html('Time taken: ' + timeElapsed + ' milliseconds');


Note the time taken to add new elements this way

image

Now using a simple technique, we can improve performance by around 300%. Instead of calling the jQuery function each time the loop iterates, first create a variable that holds all the new elements and then add this variable string outside the loop. Here’s how

var start = new Date().getTime();
var str = '';
for(var cnt=0; cnt < 200; cnt++){
     str += '<p>Lorem ipsum dolor sit amet</p>';
}
$('.container').append(str);

var timeElapsed = new Date().getTime() - start;
$('#timetaken').html('Time taken: ' + timeElapsed+ ' milliseconds');


As you can see, we used a variable called str which holds all the new elements. We then made a single jQuery call to add the new elements to the container element.

$('.container').append(str);

This way, we are not calling the jQuery function on each loop, which in turn runs a set of code and checks to complete the operation. Imagine doing this for every loop!

Result: Just 12 milliseconds.

image

Live Demo:

Slow Performing Code
Fast Performing Code




About The Author

Suprotim Agarwal
Suprotim Agarwal, Developer Technologies MVP (Microsoft Most Valuable Professional) is the founder and contributor for DevCurry, DotNetCurry and SQLServerCurry. He is the Chief Editor of a Developer Magazine called DNC Magazine. He has also authored two Books - 51 Recipes using jQuery with ASP.NET Controls. and The Absolutely Awesome jQuery CookBook.

Follow him on twitter @suprotimagarwal.

5 comments:

Anonymous said...

While caching the raw HTML in a variable is, generally, good advice, there's something off in the code provided: jQuery selectors.

jQuery selectors, specially the ones like "fetch me any element with this class" are particularly slow, since they need to crawl over all the DOM.

For an accurate comparison you should drop the selector from the first loop and use a caching variable instead, like:
for(var cnt=0, $containers = $('.container'); cnt < 200; cnt++){
$containers.append('< p>Lorem ipsum dolor sit amet< /p>');
}

Alan Krueger said...

Note that in the first example, your are repeating the $('.container') lookup as well as the Element.append() 200 times. From which of these is the majority of this time coming from?

I suspect that you'd get a similar time speed-up by just calling $('.container') once and saving the result.

Anonymous said...

I suspect you'd also get a good speed up if you put the strings into an array and concatenated them together once (as opposed to creating a new, immutable string each iteration).

var segments = [];
for(var cnt=0; cnt < 200; cnt++){
segments.push('< p >Lorem ipsum dolor sit amet');
}
$('.container').append(segments.join(''));

Suprotim Agarwal said...

Anonymous - That's a very good point about selectors you made there.

Alan - yes devs do exactly that. If the same element is to be generated, one can cache it and select the container using an 'id' if one if available. As anonymous pointed out, selectors help a great deal here.

hughdbrown - yes probably. The best way to find is to run atleast 500 iterations and compare the code.

All of you have made very good points. To highlight the context of this article, I just want to reiterate this "Now when generating a number of elements on the fly, developers usually tend to write a loop and drop this code inside the loop."

Through this post, I wanted to send a message to the devs that just because a requirement demands elements to be generated 'n' number of times, don't just drop the code in a for loop and think the task is done. Profiling is a good way to find out if your code is performing well. Devs can also use jsperf.com

Anonymous said...

Can you pl show how to load data into a gridview using asp.net - jquery - ajax - json - db?