It's a very common development pattern/problem that comes up.
Creating a bunch of repetitive DOM elements and inserting them into
the page.
It comes down to:
1) Native for loops will always be faster then calling a function
that then does the loop
2) Native inserts are faster then library inserts, but library inserts
are cross browser and may handle other niceties
3) inserting after a loop is faster then inserting in a loop:
var arr = //some long array
for (var a=0, length = arr.length; a < length; a++) {
// create string
}
// insert string
is faster then
var arr = //some long array
for (var a = 0; a < arr.length; a++) {
// create string
// insert string
}
4) Joining arrays is usually faster then concatenating strings, but
not as easy to read. I only try this if I really need the speed.
Sometimes += strings are faster.
var arr = //some long array
var data = [];
for (var a = 0; a < arr.length; a++) {
data.push(a);
}
insert data.join('')
5) DOM node vs appending strings speed is browser dependent. Chrome
and nightly safari are slightly faster creating DOM nodes, appending
them all to a doc fragment and then appending the doc fragment to the
document then at doing innerHTML. They are so fast at doing either,
just code to your preferred method for them. It won't even matter for
really long arrays. Current gen browsers are much faster at inserting
a string.
6) innerHTML = 'string' does not work in IE 6, 7, 8 for inside table
tbody and other tags.
7) watch out for IE memory leaks when using innerHTML or prototypes
remove or similar methods, clear events on your DOM first. This isn't
built in because it is very slow to traverse the DOM and remove every
event automatically and is unnecessary overhead on many occasions.
Cheers,
Josh Powell
On May 13, 8:20 am, Romek Szwarc <[email protected]> wrote:
> Thanks T.J. for this long answer.
> Maybe not many people will face such a performance problem, but this could
> be written in documentation, so we can avoid such issues at the beginning.
> This could be also good topic for PimpMyCode series at Prototype's blog.
>
> Greetings
> Romek
>
> 2009/5/13 T.J. Crowder <[email protected]>
>
>
>
>
>
> > Hi,
>
> > > As you can see third method is 4 times faster than first one.
>
> > Yes. The third method largely evaluates to setting the innerHTML
> > property of the list element, which uses the browser's built-in HTML
> > processing. Reading HTML strings and quickly turning those into the
> > displayed result is fundamentally what browsers *do*, and they're
> > highly optimized to do it as quickly as possible (people are endlessly
> > comparing browsers' page rendering times). They can do it working
> > directly on their internal structures, whereas if you create and
> > append elements via DOM methods, you're working through a third-party
> > API layered on top of the browser's internals. No surprise, then,
> > that the browser does it faster when you let it use its native
> > implementations of things. :-)
>
> > I did a similar exercise a while back (here[1]), comparing DOM methods
> > vs. Prototype's wrappers for DOM methods vs. concatenating a string
> > and setting innerHTML. The last method, innerHTML, wins on every
> > browser I tried, hands down, usually by at least one order of
> > magnitude. (Prototype's wrappers aren't very costly, but going
> > through the DOM methods is, and so they inherit that cost.) The
> > smallest discrepancy, IIRC, is on Chrome ("only" about four times
> > faster) -- but then, Chrome is freakishly fast at nearly
> > everything. :-)
>
> > [1]http://pastie.org/476791
> > --
> > T.J. Crowder
> > tj / crowder software / com
> > Independent Software Engineer, consulting services available
>
> > On May 13, 9:12 am, keemor <[email protected]> wrote:
> > > Hi,
>
> > > I'd like to present 3 ways of building ul list and compare the speed
> > > of them.
> > > I used firebug's profiler on FF3
>
> > > html:
> > > <body>
> > > <a href="#" id="go">go</a>
> > > <ul id="list"></ul>
> > > </body>
> > > $('go').observe('click',go);
>
> > > First method:
> > > Time to build (2122.406ms, 84055 wywołań)
> > > function go(e){
> > > e.stop();
> > > $('list').update();
> > > var tpl = new Template ('<li class="#{class}" id="#{id}">#{id}</
> > > li>');
> > > $R(1, 1000).each(function(i){
> > > $('list').insert(tpl.evaluate({
> > > class: 'klasa',
> > > id: i
> > > }));
> > > })
>
> > > }
>
> > > Second:
> > > Time to build (1754.548ms, 57053 wywołań)
> > > function go(e){
> > > e.stop();
> > > $('list').update();
> > > $R(1, 1000).each(function(i){
> > > var li = new Element('li', {
> > > class: 'klasa',
> > > id: i
> > > }).update(i);
> > > $('list').insert(li);
> > > })
>
> > > }
>
> > > Third:
> > > Time to build (513.747ms, 30054 wywołań)
> > > function go(e){
> > > e.stop();
> > > var tpl = new Template ('<li class="#{class}" id="#{id}">#{id}</
> > > li>');
> > > var list = new String;
> > > $R(1, 1000).each(function(i){
> > > list += tpl.evaluate({class: 'klasa', id: i});
> > > })
> > > $('list').update(list);
>
> > > }
>
> > > As you can see third method is 4 times faster than first one.
> > > In first two methods around 50% of time took
> > > extractScripts() & stripScripts() which are used in update and
> > insert
> > > methods.
>
> > > So if you have more complex RIA with many dynamic elements you can
> > > simply improve it significantly :)
>
> --
> keemor
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Prototype & script.aculo.us" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/prototype-scriptaculous?hl=en
-~----------~----~----~----~------~----~------~--~---