javascript - jQuery leaks solved, but why? - Stack Overflow

I am working on a large enterprise application with a LOT of JavaScript. Enough that I can't possi

I am working on a large enterprise application with a LOT of JavaScript. Enough that I can't possibly go through and fix all the small circular references that have been created over its past 5 years of development. While researching solutions I came across this small jQuery hack/patch:

.php/2009/07/ie-memory-leak-jquery-garbage-collector/

and decided to try it. Amazingly, it works! sIEVE shows no leaks in the places I had previously identified them and the iexplore task is maintaining a more manageable memory footprint.

My question is, why does this work? jQuery.remove calls .removeChild, which should get rid of the element, but apparently does not. The patch instead appends the target element onto a new garbage collector div, which it then clears. Why does the patch method of removal pletely free up the memory but jQuery's remove function does not? I'm hoping to understand why this works in order to possibly improve the solution before I check it in to the larger application.

I am working on a large enterprise application with a LOT of JavaScript. Enough that I can't possibly go through and fix all the small circular references that have been created over its past 5 years of development. While researching solutions I came across this small jQuery hack/patch:

http://kossovsky/index.php/2009/07/ie-memory-leak-jquery-garbage-collector/

and decided to try it. Amazingly, it works! sIEVE shows no leaks in the places I had previously identified them and the iexplore task is maintaining a more manageable memory footprint.

My question is, why does this work? jQuery.remove calls .removeChild, which should get rid of the element, but apparently does not. The patch instead appends the target element onto a new garbage collector div, which it then clears. Why does the patch method of removal pletely free up the memory but jQuery's remove function does not? I'm hoping to understand why this works in order to possibly improve the solution before I check it in to the larger application.

Share Improve this question asked Aug 25, 2011 at 16:59 JPROJPRO 1,0627 silver badges19 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 12

This is the .remove method in the current jQuery release (1.6.2). Notice that it calls .cleanData:

// keepData is for internal use only--do not document
    remove: function( selector, keepData ) {
        for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
            if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
                if ( !keepData && elem.nodeType === 1 ) {
                    jQuery.cleanData( elem.getElementsByTagName("*") );
                    jQuery.cleanData( [ elem ] );
                }

                if ( elem.parentNode ) {
                    elem.parentNode.removeChild( elem );
                }
            }
        }

        return this;
    },

And the .cleanData method which it calls, which mentions a ticket number and allegedly prevents that horrible leak (according to one of the ments):

cleanData: function( elems ) {
        var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
            deleteExpando = jQuery.support.deleteExpando;

        for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
            if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
                continue;
            }

            id = elem[ jQuery.expando ];

            if ( id ) {
                data = cache[ id ] && cache[ id ][ internalKey ];

                if ( data && data.events ) {
                    for ( var type in data.events ) {
                        if ( special[ type ] ) {
                            jQuery.event.remove( elem, type );

                        // This is a shortcut to avoid jQuery.event.remove's overhead
                        } else {
                            jQuery.removeEvent( elem, type, data.handle );
                        }
                    }

                    // Null the DOM reference to avoid IE6/7/8 leak (#7054)
                    if ( data.handle ) {
                        data.handle.elem = null;
                    }
                }

                if ( deleteExpando ) {
                    delete elem[ jQuery.expando ];

                } else if ( elem.removeAttribute ) {
                    elem.removeAttribute( jQuery.expando );
                }

                delete cache[ id ];
            }
        }
    }

And here is the ticket mentioned in the ment. Apparently it was fixed eight months ago:

http://bugs.jquery./ticket/7054#ment:10

According to Dave Methvin the solution seems to be to Ensure that the DOM element ref in an event handler is removed by cleanData to avoid an IE6/7/8 memory leak.

In other words, set references to DOM elements within event handlers to null otherwise some awesome browsers, without mentioning any names cough IE cough will leak memory.

discardElement (from your link) inserts the element into a container, and then empties the container, thereby nullifying any references to that element.

With that in mind, I would suggest upgrading jQuery. The article you point to is from 2009, and two years is roughly equivalent to four-hundred-zillion man hours of jQuery development time.

Finally, here is some interesting (and ridiculously long) reading on leak patterns in Internet Explorer:

  • Understanding and Solving Internet Explorer Leak Patterns

I'm going to theorise that it's similar to garbage collection, in that it relies on Pinned objects in the heap.

IE is treating the parent of a removed object like a pin and not clearing the removed object down properly.

The act of moving the deleted item to this generated gc container is basically removing the pin because IE knows that nothing is relying on that container.

That's my gut feeling anyway.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1741397130a4344735.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信