Ticket #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: | ||
| 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
Change History
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 );
});
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()
}
});
Please follow the bug reporting guidlines and use jsFiddle when providing test cases and demonstrations instead of pasting the code in the ticket.


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.