jQuery утечки решены, но почему? - PullRequest
13 голосов
/ 25 августа 2011

Я работаю над крупным корпоративным приложением с большим количеством JavaScript.Достаточно того, что я не могу пройти и исправить все небольшие циклические ссылки, которые были созданы за последние 5 лет разработки.При поиске решений я наткнулся на этот небольшой хак / патч jQuery:

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

и решил попробовать.Удивительно, но это работает!sIEVE не показывает утечек в местах, где я их ранее идентифицировал, и задача iexplore - поддерживать более управляемый объем памяти.

Мой вопрос: почему это работает?jQuery.remove вызывает .removeChild, который должен избавиться от элемента, но, очевидно, не делает.Вместо этого патч добавляет целевой элемент в новый div сборщика мусора, который затем очищается.Почему метод удаления патча полностью освобождает память, а функция удаления jQuery - нет?Я надеюсь понять, почему это работает для возможного улучшения решения, прежде чем регистрировать его в более крупном приложении.

Ответы [ 2 ]

12 голосов
/ 25 августа 2011

Это метод .remove в текущем выпуске jQuery (1.6.2). Обратите внимание, что он вызывает .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;
    },

И метод .cleanData, который он вызывает, который упоминает номер билета и якобы предотвращает эту ужасную утечку (согласно одному из комментариев):

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 ];
            }
        }
    }

А вот и билет, упомянутый в комментарии. Видимо, это было исправлено восемь месяцев назад:

http://bugs.jquery.com/ticket/7054#comment:10

По словам Дейва Метвина, решение, похоже, заключается в Убедитесь, что ссылка элемента DOM в обработчике событий удаляется cleanData, чтобы избежать утечки памяти в IE6 / 7/8.

Другими словами, установите ссылки на элементы DOM в обработчиках событий равными null, в противном случае некоторые замечательные браузеры, не упоминая имена кашель IE кашель будут пропускать память.

discardElement (по вашей ссылке) вставляет элемент в контейнер, а затем очищает контейнер, тем самым аннулирует любые ссылки на этот элемент.

Имея это в виду, я бы предложил обновить jQuery. Статья, на которую вы указываете, относится к 2009 году, и два года примерно эквивалентны четырем сотням миллиардов человеко-часов времени разработки jQuery.

Наконец, вот несколько интересных (и до смешного длинных) чтений о шаблонах утечек в Internet Explorer:

1 голос
/ 25 августа 2011

Я собираюсь предположить, что это похоже на сборку мусора .net в том смысле, что он опирается на закрепленные объекты в куче.

IE обрабатывает родителя удаленного объекта как пин, а не очищаетудаляемый объект должным образом.

Актом перемещения удаленного элемента в этот сгенерированный контейнер gc является в основном удаление булавки, потому что IE знает, что ничто не полагается на этот контейнер.

Это мое внутреннее чувствов любом случае.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...