Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#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 Jörn Zaefferer)

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 9 years ago by Jörn Zaefferer

Description: modified (diff)

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?

comment:2 Changed 9 years ago by Jörn Zaefferer

Status: newopen

comment:3 Changed 9 years ago by Scott González

Resolution: duplicate
Status: openclosed

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).

comment:4 Changed 9 years ago by Scott González

Duplicate of #6670.

Note: See TracTickets for help on using tickets.