#6754 closed bug (duplicate)
Autocomplete performs extremely slow on local arrays exceeding 200 items on IE Browser (6, 7)
Reported by: | asutor | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | 1.9.0 |
Component: | ui.autocomplete | Version: | 1.8.7 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description (last modified by )
Performance Analysis on Autocomplete
Current Situation
Having a local array > 200 items the performance of the display of the whole suggestion list is extremely slow under the IE.
elem.autocomplete( "search", "" );
Please refer to the following table to see the performance results.
Hints:
- the performance measurement was only investigating the execution of the _suggest function.
- IE 7.0.5730 and FF 3.6.10 were tested natively
- for IE 6 and 7 the IE Tester was used (| IETester Homepage)
- the duration is given in ms
- the timeout on IE for JS execution is set to 10 seconds
FF (3.6.10) | IE (7.0.5730) | IE 6 (IETester) | IE 7 (IETester) | |||||
---|---|---|---|---|---|---|---|---|
No. of items | page reload | without reload | page reload | without reload | page reload | without reload | page reload | without reload |
10 | 19 | 25 | 31 | 47 | 31 | 47 | 47 | 62 |
50 | 71 | 110 | 187 | 313 | 187 | 297 | 204 | 313 |
100 | 139 | 210 | 484 | 735 | 469 | 703 | 484 | 718 |
200 | 279 | 404 | 1359 | 1859 | 1344 | 1891 | 1375 | 1922 |
400 | 554 | 868 | 4531 | 5531 | 4624 | 5984 | 4656 | 5562 |
800 | 1107 | 1656 | >10000 | >10000 | >10000 | >10000 | >10000 | >10000 |
Solution and Hints
Checking the execution duration for _suggest I discovered that the code line
this.menu.refresh();
is taking the most time. The reason for this is the usage of the time consuming method children(a) within this method. There are other places within that code which using additional slow functions, but this part is the worst.
Current Implementation of refresh()
refresh: function() { var self = this; // don't refresh list items that are already adapted var items = this.element.children("li:not(.ui-menu-item):has(a)") .addClass("ui-menu-item") .attr("role", "menuitem"); items.children("a") .addClass("ui-corner-all") .attr("tabindex", -1) // mouseenter doesn't work with event delegation .mouseenter(function( event ) { self.activate( event, $(this).parent() ); }) .mouseleave(function() { self.deactivate(); }); },
A more quicker implementation of refresh()
refresh: function() { var self = this; // don't refresh list items that are already adapted var items = this.element.children("li:not(.ui-menu-item):has(a)") .addClass("ui-menu-item") .attr("role", "menuitem"); items.each(function() { var item = $(this).children(); item.addClass("ui-corner-all"); item.attr("tabindex", -1); item.attr("tabindex", -1); item.mouseenter(function( event ) { self.activate( event, $(this).parent() ); }); item.mouseleave(function() { self.deactivate(); }); }); },
Probably there is a much better solution for it but this part did help a lot (speeded up 4 times). The average display time for 400 items were under 1 s. In general using the DOM manipulation should be limited and replacing the HTML parts in whole is much quicker.
I used the following article about | JQuery performance in order to find a better solution for the current problem.
Change History (4)
comment:1 Changed 12 years ago by
Description: | modified (diff) |
---|
comment:2 Changed 12 years ago by
Status: | new → open |
---|
comment:3 Changed 12 years ago by
Resolution: | → duplicate |
---|---|
Status: | open → closed |
Thanks for the performance analysis. I had already tracked this down and came up with the same fix a few days ago. There should really be a fix in jQuery core for methods that are guaranteed not to produce duplicate items (the duplication checks are what take all the time).
So the main change you did was removing the selector from the .children() call. As we already filter with :has(a), that change makes sense and shouldn't make any sementic difference.
Could you verify that removing the selector "a" from the original code makes a noticeable difference?