Bug Tracker

Modify

Ticket #2698 (closed enhancement: fixed)

Opened 5 years ago

Last modified 15 months ago

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:
Blocking: Blocked by:

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

unload.js Download (417 bytes) - added by flesler 5 years ago.
Add this after jQuery.js

Change History

comment:1 Changed 5 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 5 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 5 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 5 years ago by flesler

Add this after jQuery.js

comment:4 Changed 5 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 4 years ago by brandon

  • Status changed from new to closed
  • Resolution set to fixed
  • Milestone changed from 1.2.4 to 1.3

Please follow the  bug reporting guidlines and use  jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.

View

Add a comment

Modify Ticket

Action
as closed
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.