Skip to main content

Bug Tracker

Side navigation

#2698 closed enhancement (fixed)

Opened April 16, 2008 06:09PM UTC

Closed May 04, 2009 04:58AM UTC

Last modified March 14, 2012 05:46AM UTC

Traversing all elements and unbinding all events causes major slowdown when leaving large pages

Reported by: magearwhig Owned by:
Priority: minor Milestone: 1.3
Component: event Version: 1.2.3
Keywords: Cc:
Blocked by: Blocking:
Description

We were experiencing major slowdowns when leaving a particular page and we traced it to:

line 2393

jQuery(window).bind("unload", function() {

jQuery("*").add(document).unbind();

});

i altered jquery slightly and it reduced the time it took for this block of code from up to over 2000ms down to 5 or 6ms

i added at line 1822

bounded: [], array to keep track of elements that have events bound

and this at what was line 1823

jQuery.event.bounded.push(elem);

so start of add function in event looks like this

add: function(elem, types, handler, data) {

jQuery.event.bounded.push(elem);

then back down at line 2393 it now looks like this

jQuery(window).bind("unload", function() {

jQuery("*").add(document).unbind();

jQuery(jQuery.event.bounded).unbind();

});

Please feel free to tell me why this is a horrible solution and what might be a better one. Thanks.

Attachments (1)
  • unload.js (0.4 KB) - added by flesler June 24, 2008 06:38PM UTC.

    Add this after jQuery.js

Change History (5)

Changed April 22, 2008 02:29AM UTC by brandon comment:1

My mind is slipping but we used to have a global cache of elements that had events bound but that caused memory leaks and worse performance in large pages.

Changed May 16, 2008 03:06AM UTC by flesler comment:2

I've been thinking about something that might speed this up.

Adding a selector filter called ':bound' that returns $.data( elem, 'handle' );

and then doing $('*:bound').unbind().

So, instead of going with an .each and then the unbind for each node, we filter with a native loop (inside $.filter) and we only call unbind on those that is neccessary.

Changed June 24, 2008 03:30PM UTC by mike.helgeso comment:3

I propose using the jQuery internal cache to unbind events, instead of traversing all elements.

jQuery(window).bind("unload", function() {
   // jQuery("*").add(document).unbind(); // old
   for ( var guid in jQuery.cache ) // iterate the cache
      if ( guid>1 && jQuery.cache[ guid ].handle ) // not window ( guid==1 )
         jQuery.event.remove( jQuery.cache[ guid ].handle.elem ); 
   });

Changed June 25, 2008 04:19AM UTC by mike.helgeso comment:4

This addition should sufficiently clean-up any stored data as well...

jQuery( window ).bind( "unload", function(){
	for ( var id in jQuery.cache ){ // iterate the cache
		if ( id>1 && jQuery.cache[ id ].handle ) // bound non-window events
			jQuery.event.remove( jQuery.cache[ id ].handle.elem ); // unbind()
		if ( id!=1 ) delete jQuery.cache[ id ]; // removeData()
		}
	});

Changed May 04, 2009 04:58AM UTC by brandon comment:5

milestone: 1.2.41.3
resolution: → fixed
status: newclosed