教程:查找內存泄漏 (JavaScript)
本主題帶領您完成使用 JavaScript 內存分析器確定并修復簡單內存問題的過程。在本教程中,我們創建一個生成大量數據的應用程序。我們預期在導航到新頁時該應用程序會釋放數據。
JavaScript 內存分析器可用于 Visual Studio 2012 更新 1 中的 Windows 8。
運行 JavaScript 內存分析器測試應用程序
-
用 Visual Studio 中,單擊“文件”>“新建”>“項目”。
-
單擊左窗格中的“JavaScript”,然后單擊中間窗格中的“導航布局應用程序”。
-
在“名稱”框中,鍵入諸如 JS_Mem_Tester 等名稱,然后單擊A“確定”。
-
在“解決方案資源管理器”中,在 pages\home 文件夾中,打開 home.html 并將以下代碼粘貼到 <body> 標記之間:
HTML<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 并用以下代碼替換所有代碼:
JavaScript(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 內存分析器之間切換。有關更多信息,請參見從 Visual Studio 運行 Windows 應用商店應用程序和在遠程計算機上運行 Windows 應用商店應用程序。
-
在“調試” 菜單上,指向“JavaScript 內存分析”,然后單擊“啟動啟動項目”。
在本教程中,我們將內存分析器連接到啟動項目。有關其他選項的信息,如將內存分析器連接到所安裝的應用程序,請參見分析內存使用情況數據 (JavaScript)。
當您啟動內存分析器時,可能會發現用戶帳戶控制正在請求運行 VsEtwCollector.exe 的權限。單擊“是”。
-
從正在運行的應用程序中,切換到 Visual Studio (Alt+Tab)。
JavaScript 內存分析器在“診斷中心”選項卡上顯示信息。
此摘要視圖中的內存圖顯示一段時間內的進程內存使用量。此視圖還提供諸如“拍攝堆快照”等命令。快照提供特定時刻有關內存使用量的詳細信息。有關更多信息,請參見分析內存使用情況數據 (JavaScript)。
-
單擊“拍攝堆快照”。
-
切換到該應用程序并單擊“啟動”按鈕。
當按“啟動”時,home.js 中的代碼生成一個大數組。我們將其用于診斷目的。
-
切換到 Visual Studio 并再次單擊“拍攝堆快照”。
此圖在摘要視圖的下窗格中顯示兩個快照。
-
可以比較快照。快照 #2 顯示以下內容:
-
堆大小(藍色文本,左側)顯著提高,到大于 1 MB。
-
堆大小自前一個快照以來的差異(紅色文本,左側)大于 400 KB。
-
堆上的對象數(藍色文本,右側)增加了數百(到超過 3,900)。
-
堆上的對象數自前一個快照以來的差異(紅色文本,右側)大于 300 個對象。
-
-
在快照 #2 中,單擊位于左側的紅色文本,顯示一個諸如 +404 KB 等的差值。
這會打開一個名為“快照 #2 - 快照 #1”的差異視圖,默認顯示支配者視圖。下圖顯示了該視圖。
在該視圖中,您會看到保留內存的對象的列表(從保留大多數內存的對象開始)。默認情況下,JavaScript 內存分析器篩選出 Windows 運行時和 Windows JavaScript 庫創建的內置對象。這有助于將信息集中于應用程序相關的代碼。
可以看到 data 對象具有超過 400 KB 的保留的大小差異值。
當一個預期對象或標識符難以找到時,在某些視圖中可以在“名稱篩選器”框中鍵入標識符名稱以查找并選擇特定標識符。
-
在標識符列表中,右擊 data 標識符,然后單擊“顯示在根視圖中”。
選定的值顯示在“快照 #2 - 快照 #1”差異視圖的根視圖中。根視圖顯示您檢查的對象相對于 Global 對象的引用位置。這可能有助于確定內存問題出現的位置。這是此時根視圖的一部分。(位于樹頂部的 Global 對象不可見。)
在根視圖中,我們可以看到 data 變量被主頁的 ready 函數調用的匿名函數引用,而且其根為包含 winControl對象的 DIV 元素。根據我們對該應用程序的了解,我們知道此控件對象引用應用程序的“啟動”按鈕。
-
切換到該應用程序并單擊“導航”按鈕。
“導航”按鈕導航到新頁。(為使該應用程序簡單起見,我們重新加載主頁。)
-
切換到 Visual Studio 并單擊“拍攝堆快照”。
在快照 #3 中,可以看到堆的大小以及堆上的對象數沒比前一個快照變化太多。下面是快照類的類似外觀:
對于本教程,我們預期在您按“啟動”后該應用程序生成的數據(數組)在您按“導航”轉到新頁時被釋放(或在此情況下,重新加載)。但是,該數據未被釋放,因此,我們將修復這個問題。
-
單擊摘要視圖中的“停止”按鈕。
修復內存問題
-
在 home.js 中,移除“導航”按鈕的事件處理代碼:
JavaScriptfunction nButtonClicked(args) { WinJS.Navigation.navigate('/pages/home/home.html'); }
用此代碼替換它:
JavaScriptfunction nButtonClicked(args) { data = null; WinJS.Navigation.navigate('/pages/home/home.html'); }
-
在“調試” 菜單上,指向“JavaScript 內存分析”,然后單擊“啟動啟動項目”。
-
按照上節所述的相同過程執行操作以拍攝三個快照。步驟摘要如下:
-
切換到 Visual Studio 并單擊“拍攝堆快照”。
-
在該應用程序中,單擊“啟動”按鈕。
-
切換到 Visual Studio 并單擊“拍攝堆快照”。
-
在該應用程序中,單擊“導航”按鈕。
-
切換到 Visual Studio 并單擊“拍攝堆快照”。
在快照 #3 中可以看到,堆大小類似于您按“啟動”并生成數據之前的堆大小。以下是快照:
-
-
在快照 #3 中,單擊在左側顯示堆大小的藍色文本。
這將打開快照 #3 的支配者視圖。這是快照 #3 的詳細信息視圖,而不是差異視圖。
-
在“名稱篩選器”框中鍵入 data。
此時,data 變量不存在于堆中。因此內存問題已解決!
from:http://msdn.microsoft.com/zh-cn/library/windows/apps/jj819178.aspx