0

I am trying to optimize some basic jquery script that traverses and hides/shows some unordered lists.

Here's the testcase in jsperf: http://jsperf.com/caching-vs-no-caching

I run the test in two browsers: Chrome and IE7/IE8 and surprisingly the cached case is slower - by a little bit but still.

The unoptimized version is:

(function( $ ) {
  $.fn.menuManipulation = function() {
    this.parents().show();
  };
})( jQuery );

$('.menu-vertical li.selected').menuManipulation();
$(".menu-vertical li.selected > ul.static").show();
$('li.static').has('ul').addClass("with-child");

and the cached one:

(function($) {  
    $.fn.menuManipulation = function() {
    this.parents().show();
    };
})(jQuery);

var menu = $('.menu-vertical');
menu.find('li.selected').menuManipulation();
menu.find('li.selected > ul.static').show();
menu.find('li.static').has('ul').addClass("with-child");

Could someone explain what am I doing wrong and why does the cached version seem to be slower?

George Katsanos
  • 13,524
  • 16
  • 62
  • 98
  • I would venture a guess that the benefit you get from the cached version doesn't outweigh the overhead of caching the data, so that it takes a little more total time to gather and store all the data for caching purposes than it does to retrieve and return the specific data that you want for the non-cached version. – taz Sep 14 '12 at 14:08

4 Answers4

5

Short answer: Selectors are actually pretty fast, but find is slow as hell. Your cached version has introduced multiple find calls - that is what is slow.

Slightly longer answer: You only really get benefir from caching the jQuery collection if you keep re-using it as-is. Take a look at this test case where the cached version clearly runs faster: http://jsperf.com/cachingjq

Jamiec
  • 133,658
  • 13
  • 134
  • 193
  • 1
    This. In my opinion, if you're using `find` a lot, there's a good chance you need to re-evaluate your selectors – BLSully Sep 14 '12 at 14:10
  • Even though the question is answered, what would be a good simple alternative to improve the original code if find is out of the question? – George Katsanos Sep 14 '12 at 14:12
2

George,

Try this in your 'cached' case and see what the performance difference is:

(function($) {  
    $.fn.menuManipulation = function() {
        this.parents().show();
    };
})(jQuery);

var menu = $('.menu-vertical');
$('li.selected', menu).menuManipulation();
$('li.selected > ul.static', menu).show();
$('li.static', menu).has('ul').addClass("with-child");
BLSully
  • 5,929
  • 1
  • 27
  • 43
1

It's debatable as to whether find() is 'slow as hell', or infact fast as hell. Your performance issues could depend on the version of jQuery your using, or the structure of your DOM.

See here for the other side of the argument for find() performance: jQuery selector performance, http://seesparkbox.com/foundry/jquery_selector_performance_testing

Benchmark test: Find() Vs Selector

Community
  • 1
  • 1
JDandChips
  • 9,780
  • 3
  • 30
  • 46
  • This article is enlightening. I wonder if the jQuery version has an impact to this. (whether you're using a legacy version or a latest version..) – George Katsanos Dec 04 '12 at 15:52
1

Cache the elements your actually going to be working on, in your case the 'li' elements.

var menu = $('.menu-vertical li');
menu.filter('.selected').children('ul.static').show().end().menuManipulation();
menu.filter('.static').has('ul').addClass("with-child");

Your "optimized" cache version is actually less optimized because of the additional and redundant searching for the li elements.

Robert Beuligmann
  • 1,434
  • 10
  • 13
  • to add some context and help the query? – George Katsanos Sep 14 '12 at 14:23
  • @GeorgeKatsanos I suppose for context you could change the variable to menuItems in my example. In terms of helping the query, caching the parent forces you to repeat the li selector in each of the subsequent statements, which is not an optimization over your "unoptimized" example. When I look to optimize a selector, $('?'), I try to minimize the $('?').length of selectors first, starting at the highest level and working down. – Robert Beuligmann Sep 14 '12 at 14:30