Skip to main content

Bug Tracker

Side navigation

#1463 closed bug (fixed)

Opened August 03, 2007 03:20PM UTC

Closed August 19, 2007 11:39PM UTC

Last modified August 20, 2007 12:09AM UTC

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)
  • index.2.html (2.7 KB) - added by offwhite August 03, 2007 08:52PM UTC.

    Revised Page

  • index.html (2.6 KB) - added by offwhite August 03, 2007 03:23PM UTC.

    The Page

  • jquery-1.1.3.1.adjusted.js (62.2 KB) - added by offwhite August 04, 2007 06:04PM UTC.

    Adjusted jQuery

  • script.2.js (3.9 KB) - added by offwhite August 03, 2007 08:51PM UTC.

    Revised Script

  • script.js (3.2 KB) - added by offwhite August 03, 2007 03:20PM UTC.

    The Script

Change History (6)

Changed August 03, 2007 07:17PM UTC by offwhite comment:1

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 August 04, 2007 06:03PM UTC by offwhite comment:2

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 August 10, 2007 06:27AM UTC by john comment:3

component: coreevent

Changed August 19, 2007 09:50PM UTC by john comment:4

owner: → john

Changed August 19, 2007 11:39PM UTC by john comment:5

resolution: → fixed
status: newclosed

Fixed in SVN rev [2783].

Changed August 20, 2007 12:09AM UTC by john comment:6

Oh, and here's the revised test that I ran:

http://dev.jquery.com/~john/ticket/ajax/faster.html