Руководство. Поиск утечек памяти (JavaScript)
В этом разделе описан процесс обнаружения и исправления простой проблемы с памятью с помощью анализатора памяти JavaScript. В этом руководстве мы создадим приложение, которое формирует большой массив данных. Предполагается, что приложение освободит эти данные при переходе на новую страницу.
Примечание
Анализатор памяти JavaScript доступен для Windows 8 в Visual Studio 2012 Обновление 1.
Запуск тестового приложения анализатора памяти JavaScript
В Visual Studio щелкните Файл > Создать > Проект.
Щелкните JavaScript в левой области, а затем щелкните Приложение навигации в средней области.
В поле Имя введите имя проекта, например "JS_Mem_Tester", и нажмите кнопку ОК.
В обозревателе решений в папке pages\home откройте файл home.html и вставьте следующий код между тегами <body>:
<div class="fragment homepage"> <header aria-label="Header content" role="banner"> <button class="win-backbutton" aria-label="Back" disabled type="button"></button> <h1 class="titlearea win-type-ellipsis"> <span class="pagetitle">Welcome to JSMemTester!</span> </h1> </header> <section aria-label="Main content" role="main"> <p>Start generating data...</p> <button class="startButton" title="start" >Start</button> <p class="statusMsg1">""</p> <p>Navigate to page... (reload)</p> <button class="navButton" title="navigate" >Navigate</button> </section> </div>
Откройте файл home.js и замените весь код следующим кодом:
(function () { "use strict"; var data; WinJS.UI.Pages.define("/pages/home/home.html", { // This function is called whenever a user navigates to this page. It // populates the page elements with the app's data. ready: function (element, options) { // TODO: Initialize the page here. var firstElem = document.querySelector('.startButton'); firstElem.addEventListener('click', sButtonClicked.bind(this)); var secondElem = document.querySelector('.navButton'); secondElem.addEventListener('click', nButtonClicked.bind(this)); }, generateData: function () { data = {}; var x = 0; var newData = "1"; for (var i = 0; i < 300; i++) { data[i] = "data" + newData; newData = newData + (100 * set[x]).toString(); if (i == 100) { x = 1; } if (i == 200) { x = 2; } } } }); function sButtonClicked(args) { this.generateData(); var elem = document.querySelector('.statusMsg1'); elem.textContent = "Done generating data (string array)."; } function nButtonClicked(args) { WinJS.Navigation.navigate('/pages/home/home.html'); } // Adding arbitrary values to sample data. var mod1 = 10; var mod2 = 100; var mod3 = 1000; var set = [mod1, mod2, mod3 ]; })();
Нажмите клавишу F5, чтобы начать отладку. Проверьте, что появляется следующая страница:
Вернитесь в Visual Studio (ALT+TAB) и нажмите SHIFT+F5, чтобы остановить отладку.
Теперь, когда мы проверили работоспособность приложения, можно проверить использование памяти.
Анализ использования памяти
На панели инструментов Отладка в раскрывающемся списке "Начать отладку" щелкните Имитатор.
Можно также щелкнуть в списке Локальный компьютер или Удаленный компьютер. Но если используется имитатор, его можно разместить рядом с Visual Studio, чтобы быстрее переключаться между запущенным приложением и анализатором памяти JavaScript. Дополнительные сведения см. в разделах Запуск приложений для Магазина Windows из Visual Studio и Запуск приложений для Магазина Windows на удаленном компьютере.
В меню Отладка выберите пункт Анализ памяти JavaScript, а затем щелкните Запустить запускаемый проект.
В этом руководстве мы прикрепим анализатор памяти к запускаемому проекту. Сведения о других вариантах, например о прикреплении анализатора памяти к установленному приложению, см. в разделе Анализ данных об использовании памяти (JavaScript).
При запуске анализатора памяти может появиться сообщение системы контроля учетных записей с запросом разрешения на запуск файла VsEtwCollector.exe. Нажмите кнопку Да.
Из запущенного приложения переключитесь в Visual Studio (ALT+TAB).
Сведения анализатора памяти JavaScript будут отображаться на вкладке Концентратор диагностики.
В графе памяти в сводном представлении отображается использование памяти процессом с течением времени. В этом представлении также доступны команды, например Сделать снимок кучи. Снимок содержит подробные сведения об использовании памяти в определенный момент времени. Дополнительные сведения см. в разделе Анализ данных об использовании памяти (JavaScript).
Щелкните Сделать снимок кучи.
Переключитесь в приложение и нажмите кнопку Start.
Код в home.js создаст большой массив при нажатии кнопки Start. Мы будем использовать его в целях диагностики.
Переключитесь в Visual Studio и снова нажмите Сделать снимок кучи.
На этом рисунке показаны два снимка в нижней области сводного представления.
Снимки можно сравнивать. Снимок 2 содержит следующую информацию:
размер кучи (синий текст слева) значительно увеличился до более чем 1 МБ;
разница в размере кучи по сравнению с предыдущим снимком (красный текст слева) составляет более 400 КБ;
количество объектов в куче (синий текст справа) увеличилось на несколько сотен (до более чем 3900);
разница в количестве объектов в куче (красных текст справа) по сравнению с предыдущим снимком составляет более 300 объектов.
На снимке 2 щелкните красный текст слева, показывающий разницу, например +404 КБ.
Будет открыто разностное представление Снимок 2- Снимок 1, которое по умолчанию является представлением "Доминаторы". Это представление показано на следующем рисунке.
В этом представлении можно увидеть отсортированный по убыванию список объектов с указанием их полного размера. По умолчанию анализатор памяти JavaScript отфильтровывает встроенные объекты, созданные средой выполнения Windows и библиотекой Windows для JavaScript. Это позволяет сосредоточиться на данных, относящихся к коду приложения.
Можно видеть, что для объекта data значение Разница полного размера превышает 400 КБ.
Совет
Если поиск нужного объекта или идентификатора вызывает затруднения, в некоторых представлениях можно ввести имя идентификатора в поле Фильтр имен, чтобы найти и выбрать определенный идентификатор.
В списке идентификаторов щелкните правой кнопкой мыши идентификатор data, а затем щелкните Показать в корневом представлении.
Выбранное значение отображается в представлении "Корни" разностного представления Снимок 2 - Снимок 1. В представлении "Корни" показано, где находится ссылка на требуемый объект относительно объекта Global. Это может помочь определить, где возникают проблемы с памятью. На рисунке ниже частично показано представление "Корни" в настоящий момент. (Объект Global в верхней части дерева не отображается.)
В представлении "Корни" можно видеть, что на переменную data ссылается анонимная функция, которая вызывается функцией ready домашней страницы и которая относится к элементу, содержащему объект winControl. Знание приложения позволяет нам сделать вывод, что этот объект элемента управления относится к кнопке Start приложения.
Переключитесь в приложение и нажмите кнопку Navigate.
Кнопка Navigate вызовет переход на новую страницу. (Чтобы не усложнять приложение, мы просто перезагружаем домашнюю страницу.)
Переключитесь в Visual Studio и нажмите Сделать снимок кучи.
В снимке №3 видно, что размер кучи и число объектов в куче не очень изменились по сравнению с предыдущим снимком. Ниже это показано на рисунках.
В этом руководстве мы ожидаем, что массив data, созданный приложением при нажатии кнопки Start, будет удален при нажатии кнопки Navigate и при переходе на новую страницу (в данном случае при перезагрузке страницы). Однако массив data не удаляется, и нам нужно исправить эту ошибку.
Нажмите кнопку Остановить в сводном представлении.
Исправления проблемы памяти
В файле home.js удалите код обработки событий для кнопки Navigate.
function nButtonClicked(args) { WinJS.Navigation.navigate('/pages/home/home.html'); }
Замените его следующим кодом:
function nButtonClicked(args) { data = null; WinJS.Navigation.navigate('/pages/home/home.html'); }
В меню Отладка выберите пункт Анализ памяти JavaScript, а затем щелкните Запустить запускаемый проект.
Выполните процедуру, описанную в предыдущем разделе, чтобы сделать три снимка. Инструкции кратко перечислены ниже.
Переключитесь в Visual Studio и нажмите Сделать снимок кучи.
В приложении нажмите кнопку Start.
Переключитесь в Visual Studio и нажмите Сделать снимок кучи.
В приложении нажмите кнопку Navigate.
Переключитесь в Visual Studio и нажмите Сделать снимок кучи.
В снимке 3 можно видеть, что размер кучи не сильно отличается от размера кучи перед нажатием кнопки Start и формированием данных. Ниже показаны снимки.
На снимке 3 щелкните синий текст слева, показывающий размер кучи.
Будет открыто представление "Доминаторы" для снимка 3. Это представление сведений о снимке 3, а не разностное представление.
В поле Фильтр имен введите data.
На этот раз в куче нет переменной data. Проблема памяти исправлена.
См. также
Основные понятия
Анализ использования памяти в приложениях для Магазина Windows (JavaScript)