JQuery selector performace and comparison problem
All three operations do the same thing. can anyone explain the reason for the 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, that's 38 seconds.)
Scenario Explanation : I have a huge table and I repeat all the rows of the table. here Guid is the unique key and class name of the table row. cell-taskname is a div inside every first column of table-row and .cell-text is a range containing text.
source to share
This is all due to the fact that selectors are processed from right to left.
In the first and second examples, basic DOM search is only for elements with a given GUID class. Then you search only within those elements for the cells.
But in the last example with one selector, the engine does it:
-
List all the items
.cell-text
. -
Remove those that do not have an ancestor mapping
.cell-taskname
from the list. -
Remove any remaining that do not have an ancestor match
.<your-guid-here>
from the list.
You can see how it takes a little longer if there are many items .cell-text
and only a few items .<your-guid-here>
. You said the item .<your-guid-here>
is unique (one row in a massive table), so the performance difference makes sense here.
Read more about right to left right in this question and his answers .
source to share
lets say that you have 100 lines of GUIDs, each containing 100.cell-taskname, each containing 100.cell-text.
- 100 GUIDS
- 10000.cell-taskname
- 1000000.cell-text
are executed from right to left, so if you do the third 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)
and if you do the first:
select all .guid (1)
find all cell-taskname in that (100)
select all cell-text in those (10000)
in the third (first) scenario, you are working with 2.01m elements
in the first (my second) scenario, you only work with 10101 items. That's why it is much faster :-)
of course these are not exact performance numbers, but it does explain the concept of selector optimization ...
source to share