Bug Tracker

Opened 12 years ago

Closed 11 years ago

Last modified 8 years ago

#2698 closed enhancement (fixed)

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 (417 bytes) - added by flesler 12 years ago.
Add this after jQuery.js

Download all attachments as: .zip

Change History (6)

comment:1 Changed 12 years ago by brandon

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.

comment:2 Changed 12 years ago by flesler

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.

comment:3 Changed 12 years ago by mike.helgeso

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 12 years ago by flesler

Attachment: unload.js added

Add this after jQuery.js

comment:4 Changed 12 years ago by mike.helgeso

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()
		}
	});

comment:7 Changed 11 years ago by brandon

Milestone: 1.2.41.3
Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.