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)
Change History (5)
Changed April 22, 2008 02:29AM UTC by comment:1
Changed May 16, 2008 03:06AM UTC by 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 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 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 comment:5
milestone: | 1.2.4 → 1.3 |
---|---|
resolution: | → fixed |
status: | new → closed |
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.