Поделиться через


Руководство. Поиск утечек памяти (JavaScript)

В этом разделе описан процесс обнаружения и исправления простой проблемы с памятью с помощью анализатора памяти JavaScript. В этом руководстве мы создадим приложение, которое формирует большой массив данных. Предполагается, что приложение освободит эти данные при переходе на новую страницу.

Примечание

Анализатор памяти JavaScript доступен для Windows 8 в Visual Studio 2012 Обновление 1.

Запуск тестового приложения анализатора памяти JavaScript

  1. В Visual Studio щелкните Файл > Создать > Проект.

  2. Щелкните JavaScript в левой области, а затем щелкните Приложение навигации в средней области.

  3. В поле Имя введите имя проекта, например "JS_Mem_Tester", и нажмите кнопку ОК.

  4. В обозревателе решений в папке 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>
    
  5. Откройте файл 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 ]; })();
    
  6. Нажмите клавишу F5, чтобы начать отладку. Проверьте, что появляется следующая страница:

    Начальный экран тестового приложения

  7. Вернитесь в Visual Studio (ALT+TAB) и нажмите SHIFT+F5, чтобы остановить отладку.

    Теперь, когда мы проверили работоспособность приложения, можно проверить использование памяти.

Анализ использования памяти

  1. На панели инструментов Отладка в раскрывающемся списке "Начать отладку" щелкните Имитатор.

    Можно также щелкнуть в списке Локальный компьютер или Удаленный компьютер. Но если используется имитатор, его можно разместить рядом с Visual Studio, чтобы быстрее переключаться между запущенным приложением и анализатором памяти JavaScript. Дополнительные сведения см. в разделах Запуск приложений для Магазина Windows из Visual Studio и Запуск приложений для Магазина Windows на удаленном компьютере.

  2. В меню Отладка выберите пункт Анализ памяти JavaScript, а затем щелкните Запустить запускаемый проект.

    В этом руководстве мы прикрепим анализатор памяти к запускаемому проекту. Сведения о других вариантах, например о прикреплении анализатора памяти к установленному приложению, см. в разделе Анализ данных об использовании памяти (JavaScript).

    При запуске анализатора памяти может появиться сообщение системы контроля учетных записей с запросом разрешения на запуск файла VsEtwCollector.exe. Нажмите кнопку Да.

  3. Из запущенного приложения переключитесь в Visual Studio (ALT+TAB).

    Сведения анализатора памяти JavaScript будут отображаться на вкладке Концентратор диагностики.

    В графе памяти в сводном представлении отображается использование памяти процессом с течением времени. В этом представлении также доступны команды, например Сделать снимок кучи. Снимок содержит подробные сведения об использовании памяти в определенный момент времени. Дополнительные сведения см. в разделе Анализ данных об использовании памяти (JavaScript).

  4. Щелкните Сделать снимок кучи.

  5. Переключитесь в приложение и нажмите кнопку Start.

    Код в home.js создаст большой массив при нажатии кнопки Start. Мы будем использовать его в целях диагностики.

  6. Переключитесь в Visual Studio и снова нажмите Сделать снимок кучи.

    На этом рисунке показаны два снимка в нижней области сводного представления.

    Сводки снимков

  7. Снимки можно сравнивать. Снимок 2 содержит следующую информацию:

    • размер кучи (синий текст слева) значительно увеличился до более чем 1 МБ;

    • разница в размере кучи по сравнению с предыдущим снимком (красный текст слева) составляет более 400 КБ;

    • количество объектов в куче (синий текст справа) увеличилось на несколько сотен (до более чем 3900);

    • разница в количестве объектов в куче (красных текст справа) по сравнению с предыдущим снимком составляет более 300 объектов.

  8. На снимке 2 щелкните красный текст слева, показывающий разницу, например +404 КБ.

    Будет открыто разностное представление Снимок 2- Снимок 1, которое по умолчанию является представлением "Доминаторы". Это представление показано на следующем рисунке.

    Различия снимков в представлении "Деноминаторы"

    В этом представлении можно увидеть отсортированный по убыванию список объектов с указанием их полного размера. По умолчанию анализатор памяти JavaScript отфильтровывает встроенные объекты, созданные средой выполнения Windows и библиотекой Windows для JavaScript. Это позволяет сосредоточиться на данных, относящихся к коду приложения.

    Можно видеть, что для объекта data значение Разница полного размера превышает 400 КБ.

    Совет

    Если поиск нужного объекта или идентификатора вызывает затруднения, в некоторых представлениях можно ввести имя идентификатора в поле Фильтр имен, чтобы найти и выбрать определенный идентификатор.

  9. В списке идентификаторов щелкните правой кнопкой мыши идентификатор data, а затем щелкните Показать в корневом представлении.

    Выбранное значение отображается в представлении "Корни" разностного представления Снимок 2 - Снимок 1. В представлении "Корни" показано, где находится ссылка на требуемый объект относительно объекта Global. Это может помочь определить, где возникают проблемы с памятью. На рисунке ниже частично показано представление "Корни" в настоящий момент. (Объект Global в верхней части дерева не отображается.)

    Различия снимков в представлении "Корневые элементы"

    В представлении "Корни" можно видеть, что на переменную data ссылается анонимная функция, которая вызывается функцией ready домашней страницы и которая относится к элементу, содержащему объект winControl. Знание приложения позволяет нам сделать вывод, что этот объект элемента управления относится к кнопке Start приложения.

  10. Переключитесь в приложение и нажмите кнопку Navigate.

    Кнопка Navigate вызовет переход на новую страницу. (Чтобы не усложнять приложение, мы просто перезагружаем домашнюю страницу.)

  11. Переключитесь в Visual Studio и нажмите Сделать снимок кучи.

    В снимке №3 видно, что размер кучи и число объектов в куче не очень изменились по сравнению с предыдущим снимком. Ниже это показано на рисунках.

    Снимок после нажатия кнопки навигации

    В этом руководстве мы ожидаем, что массив data, созданный приложением при нажатии кнопки Start, будет удален при нажатии кнопки Navigate и при переходе на новую страницу (в данном случае при перезагрузке страницы). Однако массив data не удаляется, и нам нужно исправить эту ошибку.

  12. Нажмите кнопку Остановить в сводном представлении.

Исправления проблемы памяти

  1. В файле 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'); }
    
  2. В меню Отладка выберите пункт Анализ памяти JavaScript, а затем щелкните Запустить запускаемый проект.

  3. Выполните процедуру, описанную в предыдущем разделе, чтобы сделать три снимка. Инструкции кратко перечислены ниже.

    1. Переключитесь в Visual Studio и нажмите Сделать снимок кучи.

    2. В приложении нажмите кнопку Start.

    3. Переключитесь в Visual Studio и нажмите Сделать снимок кучи.

    4. В приложении нажмите кнопку Navigate.

    5. Переключитесь в Visual Studio и нажмите Сделать снимок кучи.

    В снимке 3 можно видеть, что размер кучи не сильно отличается от размера кучи перед нажатием кнопки Start и формированием данных. Ниже показаны снимки.

    Снимок с исправленной проблемой с памятью

  4. На снимке 3 щелкните синий текст слева, показывающий размер кучи.

    Будет открыто представление "Доминаторы" для снимка 3. Это представление сведений о снимке 3, а не разностное представление.

  5. В поле Фильтр имен введите data.

    На этот раз в куче нет переменной data. Проблема памяти исправлена.

См. также

Основные понятия

Анализ использования памяти в приложениях для Магазина Windows (JavaScript)

Анализ данных об использовании памяти (JavaScript)