3

All three operation are performing same thing. can anyone explain the reason for different performance?

console.time('first');
for(guid in ALLGUID){   
   $('.'+guid).find('.cell-taskname').find('.cell-text').text()
}
console.timeEnd('first');

console.time('second');
for(guid in ALLGUID){
 $('.'+guid).find('.cell-taskname .cell-text').text()
}
console.timeEnd('second');

console.time('third');
for(guid in ALLGUID){
 $('.'+guid+' .cell-taskname .cell-text').text()
}
console.timeEnd('third');

first: ~3500.000ms

second: ~3700.000ms

third: ~38000.000ms (yes it is 38 second.)

Scenario Explanation: I have Huge table and I am iterating over all table rows. here Guid is unique key and class name of table row. cell-taskname is div inside every first column of table-row and .cell-text is span containing text.

Ritesh Chandora
  • 8,382
  • 5
  • 21
  • 38
  • 3
    I can't explain the performance difference here, but if the GUID is a unique key, why do you use it as a class name rather than as an element id? Selecting by id is much faster than selecting by class. – pdw Aug 11 '14 at 08:17
  • And not by just a little bit: http://jsperf.com/getelementbyid-id-vs-queryselector-class (you can't even see the bars for the class selector, it's so overwhelmed by `getElementById`). – T.J. Crowder Aug 11 '14 at 09:17
  • @pdw Above question is my problem its just an attempt to explain my problem. its Extremely simplified version of my problem. btw I am using ID selector. TY – Ritesh Chandora Aug 11 '14 at 09:33
  • I was aware of this fact ;) – Saurabh Sinha Aug 21 '14 at 06:38

2 Answers2

6

It all has to do with the fact that selectors are processed right-to-left.

In your first and second examples, the main search of the DOM is only for the elements with the given GUID class. Then, you only search within those elements for the cells.

But in your last example, with a single selector, the engine does this:

  1. Make a list of all .cell-text elements.

  2. Remove ones that don't have an ancestor matching .cell-taskname from the list.

  3. Remove any remaining ones that don't have an ancestor matching .<your-guid-here> from the list.

You can see how that takes a bit longer, if there are lots of .cell-text elements and only a few .<your-guid-here> elements. You've said that the .<your-guid-here> element is unique (a single row in a massive table), so the performance difference makes sense here.

More on right-to-left matching in this question and its answers.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
3

lets say you have 100 rows with GUIDs, with each 100 .cell-taskname in them, with each 100 .cell-text in them.

  • 100 GUIDS
  • 10000 .cell-taskname
  • 1000000 .cell-text

selectors are done right to left, so if you would do the 3rd example:

select all .cell-text (1m)
eliminate those that don't an ancestor .cell-taskname (still 1m)
eliminate those that don't have a higher ancestor of .guid (10k)

while if you do the first one:

select all .guid (1)
find all cell-taskname in that (100)
select all cell-text in those (10000)

in the 3rd (my first) scenario, you work with 2.01m elements

in the 1st (my second) scenario, you work with only 10101 elements. So that is why it's that much faster :-)

of course, these aren't exact performance numbers, but it does explain the concept behind selector optimizations...

DoXicK
  • 4,784
  • 24
  • 22