Bug Tracker

Opened 13 years ago

Closed 13 years ago

Last modified 13 years ago

#1463 closed bug (fixed)

jQuery slowdowns on consecutive calls

Reported by: offwhite Owned by: john
Priority: critical Milestone: 1.1.4
Component: event Version: 1.1.3
Keywords: Cc:
Blocked by: Blocking:

Description

I put together a test to see how well jQuery would perform when I use it in different ways and discovered that as I repeat the actions in the test it takes longer each time. The test creates a table with 250 cells and then adds a class name, sets a css rule and binds a click event to the span element in each table cell. I time the start and end of the function that does the work with jQuery. For some reason it does additional work on each new call to the function.

I am trying to determine the problem with the profiler in Firebug. That is what is showing me the functions like inArray are being called more times on each consecutive call.

You can see the sample here...

http://brennan.offwhite.net/fasterjquery/

I have also posted to this issue to Google Groups to see if I am somehow not using jQuery right for this test.

http://groups.google.com/group/jquery-en/browse_thread/thread/7df49bf044fe13e1/db93b9c35c44d546#db93b9c35c44d546

This is a critical problem because it will cause the page to start showing the "script is running too long" warning in FF and IE. I am having this problem in a production system.

Attachments (5)

script.js (3.2 KB) - added by offwhite 13 years ago.
The Script
index.html (2.6 KB) - added by offwhite 13 years ago.
The Page
script.2.js (3.9 KB) - added by offwhite 13 years ago.
Revised Script
index.2.html (2.7 KB) - added by offwhite 13 years ago.
Revised Page
jquery-1.1.3.1.adjusted.js (62.2 KB) - added by offwhite 13 years ago.
Adjusted jQuery

Download all attachments as: .zip

Change History (11)

Changed 13 years ago by offwhite

Attachment: script.js added

The Script

Changed 13 years ago by offwhite

Attachment: index.html added

The Page

comment:1 Changed 13 years ago by offwhite

I have found that the bind function is the cause for the additional work with each consecutive call. Leaving it off causes the problem to go away. Instead of using bind I tried the click function but it has the same problem because it simply calls the bind function internally.

I have attempted to wrap the work in the function inside of an anonymous function called with by setTimeout. That helped make the browser a little more responsive but that option is not ideal because the anonymous function can still run for longer than the default 10 seconds that FF allows before prompting the user. With just 1000 nodes this becomes a problem because there is a noticeable delay when binding events to nodes.

Changed 13 years ago by offwhite

Attachment: script.2.js added

Revised Script

Changed 13 years ago by offwhite

Attachment: index.2.html added

Revised Page

comment:2 Changed 13 years ago by offwhite

I have resolve the issue. Each time an event is bound to an element the element is stored in an array (this.global[type]). When I bind each of the 250 span elements in the large table it holds onto those 250 event bindings. When I empty and append new markup to rebuild the table the 250 old event bindings become null because they were holding onto the elements which are now gone. Then the new span elements are bound and another 250 items are put into the array. The size of the array continues to grow and it is filled with null values.

My solution was to add a couple of functions to clean the array of null values. Then in the add function that the bind function calls, the cleanEventList function is called whenever the length of the array is over 500. Using that value prevents it from being called each time add is called in my test. Otherwise it needlessly loops over the array over and over. This may not be an ideal solution. The other option is to call $.event.cleanEventList() whenever a large block of markup is removed that may have events bound to them. For a long running web application this function could also be called every few minutes like a garbage collecting thread. I will attach my adjusted version of jQuery.

Remember the function in a global list (for triggering) if (!this.global[type])

this.global[type] = [];

else if (this.global[type].length > 500) {

clean the list when it gets big this.cleanEventList();

}

Changed 13 years ago by offwhite

Attachment: jquery-1.1.3.1.adjusted.js added

Adjusted jQuery

comment:3 Changed 13 years ago by john

Component: coreevent

comment:4 Changed 13 years ago by john

Owner: set to john

comment:5 Changed 13 years ago by john

Resolution: fixed
Status: newclosed

Fixed in SVN rev [2783].

comment:6 Changed 13 years ago by john

Oh, and here's the revised test that I ran: http://dev.jquery.com/~john/ticket/ajax/faster.html

Note: See TracTickets for help on using tickets.