Re: Allow to return same NodeList object for queries like getElementsByTagName, getElementsByClassName and getElementsByName

On 2/12/10 8:05 AM, Anne van Kesteren wrote:
> Is it really a lot of performance? Our developers are not that convinced.

It depends on your use case.

If you're actually using getElementsByTagName on a largish DOM, then the 
performance effect of not having to walk that DOM multiple times is in 
fact significant.  As a simple example, consider these four tests:

javascript:var start = new Date(); for (var counter = 0; counter < 
100000; ++counter) { var str = counter + ""; 
document.getElementsByTagName(str); } var end = new Date(); alert(end - 
start);

javascript:var start = new Date(); for (var counter = 0; counter < 
10000; ++counter) { var str = counter + ""; 
document.getElementsByTagName(str).length; } var end = new Date(); 
alert(end - start);

javascript:var start = new Date(); for (var counter = 0; counter < 
100000; ++counter) { var str = counter + ""; 
document.getElementsByTagName("foo"); } var end = new Date(); alert(end 
- start);

javascript:var start = new Date(); for (var counter = 0; counter < 
10000; ++counter) { var str = counter + ""; 
document.getElementsByTagName("foo").length; } var end = new Date(); 
alert(end - start);

Note that the tests that get the length run for 10x fewer iterations 
than the ones that allow the implementation to just return an object and 
do nothing.  The ones that don't get the lengh are largely there to 
measure object creation costs.  The |counter + ""| thing is done in all 
tests to eliminate that as a source of variability.  I really hope the 
various jits are not dead-code-eliminating it too much... ;)

The net result is that test 1 creates 100,000 objects, test 2 tries to 
walk the DOM 10,000 times, test 3 and test 4 are like test 1 and 2 
respectively in UAs that create new objects, and return cached objects 
in ones that don't.

Running those on http://dromaeo.com/tests/dom-query.html gives me the 
following numbers in Firefox:

Test 1: ~4350ms
Test 2: ~2100ms
Test 3: ~80ms
Test 4: ~10ms

and in Opera 10.5 pre alpha:

Test 1: ~520ms
Test 2: ~3809ms
Test 3: ~541ms
Test 4: ~3828ms

and in Safari 4:

Test 1: ~260ms
Test 2: ~1309ms
Test 3: ~131ms (?)
Test 4: ~20ms

Given that webkit doesn't cache the nodelist, I'm not sure how to 
explain the Safari numbers; perhaps Maciej can do that.

In any case, as you can see avoiding the object-creation cost (test 1 vs 
test 3) in Gecko is quite significant due to the expense of object 
creation.  It's a 50x speedup.  As you can also see on the more useful 
test, avoiding the DOM walk each time is a 20x speedup in this case. 
This would obviously depend on the size of your DOM.

> Also it has been suggested to me that just-in-time optimizations might
> not work well if different users start polluting the same object (if
> nodelists are shared).

I would be interested in specifics here.  Nothing we're doing in Gecko 
comes to mind as a problem in that regard, especially since various 
other things in the DOM _do_ in fact guarantee returning the same object.

-Boris

Received on Friday, 12 February 2010 16:29:52 UTC