#452 ✓resolved
eno

Element#down is painfully slow in IE6/7

Reported by eno | November 19th, 2008 @ 04:26 PM | in 1.7

Element.down() ist painfully slow on IE. I think this is becuase all child elements of th element in question get Element.extend()ed, and not only the nodes to return:

down: function(element, expression, index) {

element = $(element);
if (arguments.length == 1) return element.firstDescendant();
var descendants = element.descendants(); //<- OUCH!
return expression ? Selector.findElement(descendants, expression, index) :
  descendants[index || 0];

},

Instead only those nodes should be extended, that are actually returned. A similar problem (but not with that impact) exists with up(), previous(), and next(). Judging after the source code select() and adjacent() should not be afflicted.

Comments and changes to this ticket

  • Juriy Zaytsev

    Juriy Zaytsev November 19th, 2008 @ 05:55 PM

    • Title changed from “Element.down() is painfully slow in IE6 and IE7 ” to “Element#down is painfully slow in IE6/7 ”
    • State changed from “new” to “enhancement”
  • eno

    eno November 19th, 2008 @ 06:46 PM

    Hi juriy, at the current state I would call this more than a bug than just an area for improvement. Here I got some numbers, on a 1.2 MB HTML with several 10000 nodes in it.

    A $('node_close_to_top').down('a') takes 13500 msecs on IE6, an even bigger amount of time on IE7 (our results usually show an additional 30-50%). But the same code still needs 350 msecs on FF3. An equivalent call using peppy that just extends the one returned node needs no time at all (0 msecs) on all browsers.

    So fixing that code, i.e. not extending all descendants, would speed up things on other browsers as well.

  • Juriy Zaytsev

    Juriy Zaytsev November 19th, 2008 @ 06:49 PM

    A good example of why element extension sucks ;) I'll try to cook something up as soon as I get a chance.

  • Tobie Langel

    Tobie Langel November 19th, 2008 @ 07:12 PM

    A good example of why element extension sucks ;) I'll try to cook something up as soon as I get a chance.

    Yes... but at the same time... a 1.2 MB HTML file isn't exactly a common occurrence.

  • Juriy Zaytsev

    Juriy Zaytsev November 19th, 2008 @ 07:23 PM

    Yes... but at the same time... a 1.2 MB HTML file isn't exactly a common occurrence.

    True, although 120KB (10x less) is a bit more common occurrence, and if that takes 1.3 sec (as per author's observations) vs. near-zero for non-extending version, than it kind of makes sense to tackle this issue.

  • eno

    eno November 20th, 2008 @ 12:38 PM

    If only I would know how to use the Selector class with non extended objects - then this one would be easy. Someone lend me a hand?

  • Juriy Zaytsev

    Juriy Zaytsev November 20th, 2008 @ 03:16 PM

    @eno

    Perhaps:

    
    (function(){
      var oSelector = new Selector('.someClass');
      return $A(parentElement.getElementsByTagName('*')).find(function(element) {
        return oSelector.match(element);
      });
    })();
    
    
  • Andrew Dupont

    Andrew Dupont November 29th, 2008 @ 05:16 AM

    • Tag set to ie, selector
    • Milestone set to 1.7
    • State changed from “enhancement” to “bug”
    • Assigned user set to “Andrew Dupont”

    Yeah, I don't mind taking this on as a bug. Marking it for 1.6.1, but I'll try to get to it sooner if I have time.

  • eno

    eno December 2nd, 2008 @ 12:26 PM

    @andrew: thank you for your efforts. If I can be of any help, please let me know.

  • Andrew Dupont

    Andrew Dupont December 3rd, 2008 @ 05:33 AM

    Eno, just noticed the source code for Element#down is different in 1.6.0.3 — we no longer select all descendants indiscriminately. Can you run your performance tests against 1.6.0.3? It'll help to know what we're dealing with.

  • eno

    eno December 3rd, 2008 @ 12:13 PM

    Sure:

    = Test setup =

    All measurements are done on the same machine; the Windows stuff is inside a virtualbox on WinXP.

    // This is the measurement code

    function timed_execution(fun) { var now = (new Date).getTime(); var r = fun(); alert("Prototype " + Prototype.Version + " on " + navigator.userAgent + ": " + ((new Date).getTime() - now) + " msecs."); return r; }

    function find_node(selector) { var node = $("some_top_node") timed_execution(function() { node.down(selector); }); }

    // This is the relevant part of the HTML

    ...
    ... about 10000 nodes, including nodes with class "area"

    = Results =

    Note: two values indicate a huge difference between the first run and subsequent runs.

    == Finding a node close to the start node: find_node(".area") (Note that we havy many nodes that match that selector)

    on Prototype 1.6.0.1

    Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 560/58

    Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 600

    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 11967/500

    on Prototype 1.6.0.3

    Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 22

    Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 30

    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 580/160

    == Finding a node remote from the start node find_node(".stopper")

    on Prototype 1.6.0.1

    Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 550/56

    Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 630

    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 12100/470

    on Prototype 1.6.0.3

    Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 16

    Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 20

    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 150

    == Finding a non-existing node find_node(".invalid_me_class")

    on Prototype 1.6.0.1

    Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 550/56

    Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 600

    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 12100/500

    on Prototype 1.6.0.3

    Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 16

    Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 20

    Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 150

    ================================================================

    There is a huge improvement between 1.6.0.1 (which is what we are running right now because it comes w/Rails) and 1.6.0.3. Apparently you have made a remarkably good job w/that release! Flowers!

    But there is still a way to go towards real snappiness, especially if you have a number of matching nodes. Besides, on IE 7 it still "feels" slow and a way slower than 150 msecs indicate. (I guess there arer strange things going on somewhere else.)

  • eno

    eno December 3rd, 2008 @ 12:18 PM

    I hope this gets formatted properly...

    Test setup

    All measurements are done on the same machine; the Windows stuff is inside a virtualbox on WinXP.

    
    
    // This is the measurement code
    
    function timed_execution(fun) {
      var now = (new Date).getTime();
      var r = fun();
      alert("Prototype " + Prototype.Version + " on " + navigator.userAgent + ": " + ((new Date).getTime() - now) + " msecs.");
      return r;
    }
    
    function find_node(selector) {
      var node = $("some_top_node")
      timed_execution(function() { node.down(selector); });
    }
    
    // This is the relevant part of the HTML
    
    <div class="activetab_bodybox">
      ...
      <div id="rights" class="single_view_content_group">
        ... several thousand similar nodes, including nodes with class "area"
      </div>
      <div class="stopper">
      </div>
    </div>
    
    

    Results

    Note: two values indicate a huge difference between the first run and subsequent runs.

    Finding a node close to the start node: find_node(".area")

    on Prototype 1.6.0.1

    • Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 560/58
    • Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 600
    • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 11967/500

    on Prototype 1.6.0.3

    • Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 22
    • Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 30
    • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 580/160

    Finding a node remote from the start node find_node(".stopper")

    on Prototype 1.6.0.1

    • Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 550/56
    • Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 630
    • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 12100/470

    on Prototype 1.6.0.3

    • Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 16
    • Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 20
    • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 150

    Finding a non-existing node find_node(".invalid_me_class")

    on Prototype 1.6.0.1

    • Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 550/56
    • Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 600
    • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 12100/500

    on Prototype 1.6.0.3

    • Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; de; rv:1.9.0.3) Gecko/2008092414 Firefox/3.0.3: 16
    • Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.18) Gecko/20081029 Firefox/2.0.0.18: 20
    • Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1): 150

    There is a huge improvement between 1.6.0.1 (which is what we are running right now because it comes w/Rails) and 1.6.0.3. Apparently you have made a remarkably good job w/that release! Flowers!

    But there is still a way to go towards real snappiness, especially if you have a number of matching nodes. Besides, on IE 7 it still "feels" slow and a way slower than 150 msecs indicate. (I guess there are some strange things going on somewhere else.)

    /eno

  • GitHub Robot

    GitHub Robot March 5th, 2009 @ 08:56 PM

    • State changed from “bug” to “resolved”

    (from [e88f22e0c35e2a787c3f4ee89d916f0adfe9244a]) Redefine Element#down in IE 6-7 to avoid extending all descendants when no selector is given. [#452 state:resolved] (eno, Andrew Dupont) http://github.com/sstephenson/pr...

  • eno

    eno March 9th, 2009 @ 11:32 AM

    I am afraid that the patch is npt working as advertised, for a numbr of reasons:

    • the "if (Prototype.BrowserFeatures.ElementExtensions)" verification works just the other way around, and should be "if (!Prototype.BrowserFeatures.ElementExtensions)"
    • the patch only works when no CSS selector is given
    • and finally it is not Element#down, which should be fixed, but the selecting code (i.e. select should not extend non-matching nodes)

    As I cannot reopen that ticket I will file a new one, which points here.

  • eno

    eno March 9th, 2009 @ 11:38 AM

    ... and which now is in #586

  • Anselm Helbig

    Anselm Helbig March 9th, 2009 @ 11:52 AM

    I made a synthetic test case for this issue:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

    <head>
      <script type="text/javascript" src="prototype.js"></script>
      <script type="text/javascript">
    
    

    function timed_execution(fun) {

    var now = (new Date).getTime();
    var r = fun();
    alert("Prototype " + Prototype.Version + " on " + navigator.userAgent + ": " + ((new Date).getTime() - now) + " msecs.");
    return r;
    
    

    } function find_node(selector) {

    timed_execution(Element.down.curry('top_node', selector));
    
    

    } function make_nodes(how_many) {

    var parent = document.getElementById('sub_node');
    var child = parent.firstChild;
    while (child && child.nodeType != 1) 
      child = child.nextSibling;
    for (var i = 0; i < how_many; i++) 
      parent.appendChild(child.cloneNode(true));
    
    

    } function measure() {

    var options = document.location.search.toQueryParams();
    make_nodes(options.how_many || 1000);
    find_node(options.selector || 'stopper');
    
    

    }

      </script>
    </head>
    
    <body onload="measure()">
      <div id="top_node">
        <div class="menu"></div>
        <div id="sub_node"><div>foo</div></div>
        <div class="stopper"></div>
      </div>
    </body>
    
    

    Here are the numbers I can with the default settings:

    • Prototype 1.6.0.1 / IE6: 10075 ms
    • Prototype 1.6.0.3 / IE6: 10 ms
    • Prototype 1.6.0.1 / FF3/Linux: 21 ms
    • Prototype 1.6.0.3 / FF3/Linux: 6 ms

    So as far as this test case is concerned, this issue should be resolved in Prototype 1.6.0.3.

  • eno

    eno March 9th, 2009 @ 11:55 AM

    In opposite to what I said #586 won't fix that ticket in the non-selector case. Andrew's patch, however, might, if the condition check is done in the right way.

  • Tobie Langel

    Tobie Langel July 24th, 2009 @ 04:05 AM

    • Tag cleared.

    [not-tagged:"ie" not-tagged:"ie6" not-tagged:"ie7" not-tagged:"ie8" bulk edit command]

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

The Prototype JavaScript library.

Shared Ticket Bins

Referenced by

Pages