Search and Top Navigation
#6754 closed bug (duplicate)
Opened December 16, 2010 10:43AM UTC
Closed December 16, 2010 12:55PM UTC
Last modified December 16, 2010 12:55PM UTC
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
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.
Attachments (0)
Change History (4)
Changed December 16, 2010 11:00AM UTC by comment:1
description: | \ == 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 ([http://www.my-debugbar.com/wiki/IETester/HomePage | 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 [http://www.artzstudio.com/2009/04/jquery-performance-rules/ | JQuery performance] in order to find a better solution for the current problem. → == 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 ([http://www.my-debugbar.com/wiki/IETester/HomePage | 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 [http://www.artzstudio.com/2009/04/jquery-performance-rules/ | JQuery performance] in order to find a better solution for the current problem. |
---|
Changed December 16, 2010 11:01AM UTC by comment:2
status: | new → open |
---|
Changed December 16, 2010 12:55PM UTC by comment:3
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?