Understand memory leaks in JavaScript applications / Понимание утечек памяти в приложениях на JavaScript

→It's good practice to have a standard method that is responsible for making an object eligible for garbage collection. The primary purpose of a destroy function is to centralize the responsibility for cleaning up anything that the object has done that will:
1. Prevent its reference count from dropping to 0 (for example, removing problematic event listeners and callbacks and unregistering from any services).
2. Consume unnecessary CPU cycles, such as intervals or animations.
0 Считается хорошим тоном иметь стандартный метод, отвечающий за подготовку объекта для уничтожения сборщиком мусора. Основная цель этого метода заключается в централизации всех действий, необходимых для зачистки всего, что может позволить сборщику мусора посчитать объект используемым. Например:
1. Уничтожить всевозможные ссылки на объект, чтобы счетчик внешних ссылок равнялся нулю (к примеру, убрать обработчики событий, колбэки, итд)
2. Избавиться от всевозможныйх циклов, такие как интервалы или анимация.
→Listing 5. assets/scripts/main.js
0 Листинг 5. assets/scripts/main.js
→To clean up the issue, trigger the destroy method that was added to the leaker object before nulling the stored reference to it, by updating the click handler for the destroy button, as in Listing 5.
0 Чтобы исправить эту ситуацию, нужно выполнить метод destroy, который был добавлен к классу Leaker, прежде, чем присваивать null переменной leak, которая является ссылкой на наш объект. Для этого необходимо обновить обработчик, висящий на кнопке Destroy, согласно листингу 5.
→Now, when you repeat steps 1-9 in the section above, you should see that in snapshot three the Leaker object has persisted and the interval continues running forever. So what happened? Any local variable that is referenced in a closure is retained by the closure for as long as the closure exists. To ensure that the callback for the setInterval method executed with access to Leaker instance's scope, the this variable was assigned to the local variable self, which was used to trigger onInterval from within the closure. When onInterval fires, it has access to any instance variables in the Leaker object including self. However, the Leaker object is not garbage collected for as long as the event listener exists.
0 Теперь, если вы повторите шаги с первого по девятый из предыдущей части, на третьем снимке вы обнаружите, что объект типа Leaker все еще присутствует, а интервал продолжает исполняться бесконечно. Итак, что же произошло? Если сослаться на локальную переменную из замыкания, она остается в памяти до тех пор, пока замыкание существует. Чтобы обеспечить выполнение колбэка в методе setInterval с доступам к области видимости внешнего объекта типа Leaker, переменная this присваивается локальной переменной self, которая используется для вызова onInterval изнутри замыкания. Когда onInterval исполняется, он имеет доступ к любым переменным объекта Leaker, включая преременную self. Тем не менее, объект Leaker не уничтожается сборщиком мусора до тех пор, пока обработчик события существует.
→Listing 4. assets/scripts/leaker.js
0 Листинг 4. assets/scripts/leaker.js
→One easy way to prevent an object from being garbage-collected is to have an interval or timeout that references the object in its callback. To see this in action, update the leaker.js class as in Listing 4.
0 Один из самый простых способов создать "утечку" объекта – создать интервал или таймаут, колбэк которого ссылается на объект. Для достижения подобного результата обновите leaker.js в соответствии с листингом 4.
→Hooray! Garbage collection works. Now it's time to break it.
0 Ура! Сборщик мусора работает исправно. Настало время сломать его.
→9 Filter the third snapshot looking for instances of the Leaker class. You should find no instances. Alternately, with the third snapshot loaded, switch analysis modes from Summary to Comparison and compare the third and second snapshots. You should see a delta of -1 (one instance of the Leaker object was released between the two snapshots).
0 9. Отфильтруйте третий снимок, чтобы видеть экземпляры класса Leaker. Результат должен быть сноав пуст. Также, выбрав третий снимок, вы можете переключиться с режима Summary (Сводка) на режим Comparison (Сравнение) и сравнить третий и второй снимки. Вы должны увидеть разницу в -1 (один объект типа Leaker был уничтожен между этими снимками).
→8. Take a third heap snapshot.
0 8. Сделайте третий снимок.
→7. Return focus to the web page and select Destroy.
0 7. Верните фокус в окно и нажмите кнопку "Destroy".
→Figure 3. Snapshot instance
0 Рисунок 3. Экземпляры класса
→6. Filter the first snapshot looking for instances of the Leaker class. You should find no instances. Switch to the second snapshot, and you should find one instance, as in Figure 3.
0 6. Отфильтруйте первый снимок, чтобы увидеть экземплары класса Leaker. Результат должен быть пустым. Переключитесь на второй снимок и вы должны будете обнаружить один экземпляр класса (см. Рисунок 3).
→5. Take another heap snapshot.
0 5. Сделайте еще один снимок.
→4. Return focus to the web page and select Start.
0 4. Верните фокус на страницу и нажмите кнопку "Start"
→Figure 2. Profiles tab
0 Рисунок 2. Вкладка "Profiles"
→3. Go to the Profiles tab and take a heap snapshot, as shown in Figure 2.
0 3. Перейдите во вкладку Profiles, выберите пункт "Take Heap Snapshot" и нажмите "Start".
→2. Open the developer tools by opening the View menu and selecting the Develop submenu. Select the Developer Tools command.
0 2. Откройте панель Developer Tools (Нажмите F12 или испоьзуйте меню Просмотр, Разработчикам, Инструменты разработчика).
→1. Load the index page in Chrome. Because you're loading jQuery directly from Google, an Internet connection is required to run the sample.
0 1. Откройте страницу index.html в браузере Chrome. Поскольку в нашем примере jQuery загружается с сервера Google, необходимо подключение к Интернету.
→At this point, you're ready to create an object, observe it in memory, and then free it.
0 На этом этапе все готово для того, чтобы создать объект, увидеть его в профайлере и, затем, уничтожить его, освободив выделенную область памяти.
→Listing 3. assets/scripts/main.js
0 Листинг 3. assets/scripts/main.js
Резюме
Пол:
мужчина
Родной язык:
русский
С нами:
с 20 февраля 2009 г. (6449 дней)
Не является членом клуба.
Деятельность:
349 версий перевода с общим рейтингом 14
15 комментариев
Карма: 2 (оценок: 2)
Написать Stutzer личное сообщение