共用方式為


教學課程:尋找記憶體流失 (JavaScript)

本主題會帶領您使用 JavaScript 記憶體分析器找出並修正簡單的記憶體問題。在本教學課程中,我們會建立可產生大型資料陣列的應用程式。當我們巡覽至新頁面時,預期應用程式會處理資料。

注意事項注意事項

Windows 8 的 Visual Studio 2012 Update 1 已提供使用 JavaScript 記憶體分析器。

執行 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 記憶體分析器之間切換。如需詳細資訊,請參閱 從 Visual Studio 執行 Windows 市集應用程式在遠端電腦執行 Windows 市集應用程式

  2. 在 [偵錯] 功能表上指向 [JavaScript 記憶體分析],然後按一下 [啟動啟始專案]。

    在本教學課程中,我們會將記憶體分析器附加至啟始專案。如需其他選項 (例如將記憶體分析器附加至已安裝的應用程式) 的詳細資訊,請參閱分析記憶體使用量資料 (JavaScript)

    當您啟動記憶體分析器時,可能會出現 [使用者帳戶控制] 要求您提供執行 VsEtwCollector.exe 的權限。請按一下 []。

  3. 當應用程式仍在執行時,切換至 Visual Studio (Alt+Tab)。

    JavaScript 記憶體分析器的 [診斷中樞] 索引標籤會顯示相關資訊。

    摘要檢視中的記憶體圖表會顯示一段時間後的處理序記憶體使用量。此檢視也會提供像是 [擷取堆積快照] 這類命令。快照可提供特定時間的記憶體使用量詳細資訊。如需詳細資訊,請參閱分析記憶體使用量資料 (JavaScript)

  4. 按一下 [擷取堆積快照]。

  5. 切換至應用程式,然後按一下 [啟動] 按鈕。

    按下 [啟動] 時,home.js 中的程式碼會產生一個大型陣列。我們將使用這個陣列進行診斷。

  6. 切換至 Visual Studio 並再次按一下 [擷取堆積快照]。

    下圖顯示位於摘要檢視下方窗格的兩個快照。

    快照摘要

  7. 您可以比較這兩個快照。快照 #2 顯示下列資訊:

    • 堆積大小 (左邊的藍色文字) 大幅增加到 1 MB 以上。

    • 與上一個快照在堆積大小的差異 (左邊的紅色文字) 超過 400 KB。

    • 堆積的物件數目 (右邊的藍色文字) 增加了數百個 (超過了 3,900 個)。

    • 與上一個快照相比,堆積的物件數目差異 (右邊的紅色文字) 超過 300 個。

  8. 在快照 #2 中,按一下左邊的紅色文字 (顯示像是 +404 KB 這種差異值)。

    如此將開啟差異檢視 (稱為 [快照 #2 - 快照 #1]),其中預設顯示 [主導者] 檢視。下圖顯示這個檢視。

    [主導者] 檢視中的快照差異

    在這個檢視中,您會看到保留記憶體的物件清單,而順序則是從保留最多記憶體的物件開始。根據預設,JavaScript 記憶體分析器會篩選 Windows 執行階段和 Windows Library for JavaScript 所建立的內建物件。這有助於將重點放在應用程式相關的程式碼資訊。

    您可以看到 data 物件有超過 400 KB 的 [保留大小差異] 值。

    提示

    很難找到所需物件或識別項時,您可以在某些檢視的 [名稱篩選] 方塊中輸入識別項名稱,尋找並選取特定識別項。

  9. 以滑鼠右鍵按一下識別項清單中的 [data] 識別項,然後按一下 [在根檢視中顯示]。

    選取的值隨即出現在 [快照 #2 –快照 #1] 差異檢視的 [根] 檢視中。[根] 檢視會顯示您要檢查的物件與 Global 物件的相對參考位置。這有助於識別記憶體問題發生的位置。以下是 [根] 檢視此時的部分內容 (看不到位於樹狀結構頂端的 Global 物件)。

    [根] 檢視中的快照差異比對

    在 [根] 檢視中,我們可以看到 data 變數是由首頁的 ready 函式呼叫的匿名函式所參考,而這個變數的根項目就是包含 winControl 物件的 DIV 項目。從我們對於應用程式的知識可知道,這個控制項物件表示應用程式的 [啟動] 按鈕。

  10. 切換至應用程式,然後按一下 [巡覽] 按鈕。

    [巡覽] 按鈕會讓應用程式巡覽至新頁面 (為了保持應用程式的簡單性,我們在此只重新載入首頁)。

  11. 切換至 Visual Studio,然後按一下 [擷取堆積快照]。

    在快照 #3,您可以看到與上一個快照相比,堆積的大小和堆積的物件數目並未改變許多。這三個快照如下所示:

    按下 [巡覽] 按鈕後的快照

    在本教學課程中,我們預期在按下應用程式的 [巡覽] 並移至新網頁 (在此例中為重新載入) 時,可以處置按下 [啟動] 按鈕之後產生的資料 (陣列)。不過,這麼做並沒有處置資料,因此我們將修正這個問題。

  12. 按一下摘要檢視中的 [停止] 按鈕。

修正記憶體問題

  1. 在 home.js 中,移除 [巡覽] 按鈕的事件處理程式碼:

        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. 按一下應用程式中的 [啟動] 按鈕。

    3. 切換至 Visual Studio,然後按一下 [擷取堆積快照]。

    4. 按一下應用程式中的 [巡覽] 按鈕。

    5. 切換至 Visual Studio,然後按一下 [擷取堆積快照]。

    您可以看到,快照 #3 中的堆積大小與按下 [啟動] 並產生資料之前的堆積大小相似。這些快照如下所示:

    已修正記憶體問題的快照

  4. 在快照 #3 中,按一下顯示在左邊的藍色堆積大小文字。

    快照 #3 的 [主導者] 檢視隨即開啟。這是快照 #3 的詳細檢視,不是差異檢視。

  5. 在 [名稱篩選] 方塊中,輸入 data。

    此時 data 變數並未出現在堆積中,表示記憶體問題已經修正!

請參閱

概念

分析 Windows 市集應用程式中的記憶體使用量 (JavaScript)

分析記憶體使用量資料 (JavaScript)