jQuery 1.4.3 perf degrade (v4)

Revision 4 of this benchmark created by Charles McNulty on


Description

This is my attempt to prove the regression in performance that occurred with in 1.4.4, with this commit. I've then applied this plugin to the third test to show how easy it is to bring 1.4.3 performance back into 1.6.

This bug has been closed as "wontfix", for the following stated reason:

Both the createRange and sourceIndex code branches failed on disconnected DOM nodes, nodes in separate DOM documents, and nodes in non-HTML documents. Replacing that code with this yields much better cross-platform results overall.

It should be noted, however that in my tests with disconnected DOM nodes within 1.5.2, all browsers produce nonsensical, and different results upon sorting (including different results within the same browser upon refreshing). Therefore, this change didn't appear to improve the situation for sorting disconnected nodes. I didn't do any tests regarding separate DOM documents (Does this refer to pulling in nodes from an iframe for instance?) nor non-HTML documents. What would be nice though, is test cases that demonstrate the problem. This plugin passes all of the unit tests as of the release of 1.5.2.

I don't deny that sourceIndex could be problematic, however, it's my belief that the performance decrease is severe enough under certain conditions in IE7/8 that we need some method of both preserving the sourceIndex method of sorting where we can, while also addressing whatever testable issues exist with sourceIndex. That would result, unfortunately in more code than was in 1.4.2, rather than less code as was committed, but if jQuery is serious in support for IE 6,7 and 8 serious consideration needs to be made to the performance of those browsers.

Preparation HTML

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>var a = jQuery.noConflict();</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
<script>var b = jQuery.noConflict();</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script>
<script>

(function($) {

 if ("sourceIndex" in document.documentElement) {

  var baseHasDuplicate = true,
      sortOrder = null;

  // Here we check if the JavaScript engine is using some sort of
  // optimization where it does not always call our comparision
  // function. If that is the case, discard the hasDuplicate value.
  //   Thus far that includes Google Chrome.
  [0, 0].sort(function() {
   baseHasDuplicate = false;
   return 0;
  });

  sortOrder = function(a, b) {
   if (!a.sourceIndex || !b.sourceIndex) {
    if (a == b) {
     hasDuplicate = true;
    }
    return a.sourceIndex ? -1 : 1;
   }

   var ret = a.sourceIndex - b.sourceIndex;
   if (ret === 0) {
    hasDuplicate = true;
   }
   return ret;
  };

  $.unique = function(results) {
   if (sortOrder) {
    hasDuplicate = baseHasDuplicate;
    results.sort(sortOrder);

    if (hasDuplicate) {
     for (var i = 1; i < results.length; i++) {
      if (results[i] === results[i - 1]) {
       results.splice(i--, 1);
      }
     }
    }
   }

   return results;
  };
 }
})(jQuery);


var c = jQuery.noConflict();</script>

<style>
input, select, ul, div {
   display: none; 
}
</style>

<div id="items">  
</div>

<script>
  var amt = 50,
      $jq_142 = a('#items'),
      $jq_16 = b('#items'),
      $jq_16_with_fix = c('#items'),
      elems = [];
  
  for (var i = 0; i < amt; i++) {
   elems.push('<ul><li>foo</li></ul>');
   elems.push('<div>hmm</div>');
   elems.push('<input type="hidden" name="hoo' + i + '" /> ')
   elems.push('<select><option value="1">foo</option></select>')
  }
  
  $jq_142.html(elems.join(""));
  $jq_16.html(elems.join(""));
  $jq_16_with_fix.html(elems.join(""));
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
version 1.4.2
$jq_142.find('li').add('#items');
ready
version 1.6
$jq_16.find('li').add('#items');
ready
1.6 with fix
$jq_16_with_fix.find('li').add('#items');
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Charles McNulty on
  • Revision 4: published by Charles McNulty on
  • Revision 5: published by Charles McNulty on
  • Revision 6: published by Volker Mische on
  • Revision 7: published on