若是上篇中的Timeline面板所提供的信息不能知足你的要求,你可使用Profiles面板,利用這個面板你能夠追蹤網頁程序的內存泄漏問題,進一步提高程序的JavaScript執行性能。javascript
當前使用的Chrome最新版爲54.0.2840.71,這個版本的Profiles面板比以前提供的功能更多也更強大,下面是該面板所包含的功能點:java
經過選擇Record JavaScript CPU Profile,而後點擊Start,結合你所要分析的具體場景,你能夠從新加載網頁,或者在網頁上進行交互,甚至什麼都不操做。最後點擊Stop,完成記錄操做。正則表達式
有三種不一樣的視圖可供選擇:chrome
咱們以Chart視圖爲例分析一下JS的執行的性能狀況:數組
該視圖會以時間順序展現CPU的性能狀況,視圖主要分紅兩塊:瀏覽器
視圖中的函數顏色不一樣於其它的面板,這裏面的函數顏色標記是隨機顯示的。然而相同的函數調用顏色標記是相同的。緩存
其中縱軸表示的函數調用堆棧高度僅僅函數的調用嵌套層次比較深,不表示其重要性很高,可是橫軸上一個很寬的柱形條則意味着函數的調用須要一個很長的時間去完成,那麼你就考慮去作一些優化操做,具體能夠參見網絡性能優化方案及裏面的相關參考文檔。性能優化
將鼠標移到Call Stacks中的函數上能夠顯示函數的名稱和時間相關的數據,會提供以下信息:網絡
經過建立堆快照能夠查看建立快照時網頁上的JS對象和DOM節點的內存分佈狀況。利用該工具你能夠建立JS的堆快照、內存分析圖、對比堆快照以及定位內存泄漏問題。選中Take Heap Snapshot,點擊Take Snapshot按鈕便可獲取快照,在每一次獲取快照前都會自動執行垃圾回收操做。閉包
快照最初會存儲在渲染進程的內存之中,當咱們點擊建立快照按鈕來查看時纔會被傳輸到DevTools中,當快照被加載到DevTools裏面並通過解析以後,在快照標題下方的文字顯示是數字就是可訪問到的JS對象總的大小。
堆快照提供了不一樣的視角來進行查看:
該視圖會顯示全部的對象信息,點擊其中的一個對象進行展開可查看更詳細的實例信息。鼠標移動到某個對象上會顯示該對象實例的詳情信息。
圖中的各列的具體含義以下:
Shallow size和Retained size的區別?Shallow size是對象自己佔用內存的大小,不包含它所引用的對象。Retained size是該對象自己的Shallow size,加上能從該對象直接或者間接訪問到對象的Shallow size之和。也就是說Retained size是該對象被GC以後所能回收到內存的總和。
在展開構造函數,則會列出該函數相關的全部對象實例,能夠查看該對象的Shallow size和Retained size,在@符號後面的數字是該對象的惟一標識ID。
其中黃色的對象表示在它被某個JS所引用,而紅色的對象表示由黃色背景色引用被分離開出的節點。
這些構造函數都表明什麼含義呢?
window
)和經過它引用的對象之間的中間對象,若是一個對象是由Person構造函數生成並被全局對象所引用,那麼它們的引用路徑關係就像這樣[global] > (global property) > Person。這跟常規的對象之間直接引用相比,採用中間對象主要是考慮性能的緣由。全局對象的改變是很頻繁的,而非全局變量的屬性訪問最優化方案對全局變量是不適用的。經過比較多個快照之間的差別來找出內存泄露的對象,爲了驗證某個程序的操做不會引發內存泄露(一般會執行一個操做後再執行一個對應的相反操做,好比打開一個文檔後再關閉它,應該是沒有產生內存泄露問題的),你能夠執行以下步驟:
切換到Comparison視圖以後,就能夠看到兩個不一樣的快照之間的差異。
該視圖本質上就是應用程序的對象結構的「鳥瞰圖」,容許你去深刻分析函數的閉包,瞭解應用程序底層的內存使用狀況。
這個視圖提供了多個入口:
閉包小建議: 在快照的分析中命名函數的閉包相比匿名函數的閉包更容易區分。
Google上提供的例子和圖以下:
function createLargeClosure() { var largeStr = new Array(1000000).join('x'); var lC = function() { // 匿名函數 return largeStr; }; return lC; }
function createLargeClosure() { var largeStr = new Array(1000000).join('x'); var lC = function lC() { // 命名函數 return largeStr; }; return lC; }
該視圖是堆快照的總的分佈統計狀況,這個直接上圖就能夠了:
仍是把Google提供的內存泄露的小例子貼出來:
DOM內存泄露可能比你想象的要大,考慮一下下面的例子-何時#tree節點被釋放掉?
var select = document.querySelector; var treeRef = select("#tree"); var leafRef = select("#leaf"); var body = select("body"); body.removeChild(treeRef); //因爲treeRef #tree不能被釋放 treeRef = null; //因爲leafRef的間接引用 #tree仍是不能被釋放 leafRef = null; //如今沒有被引用,#tree這個時候才能夠被釋放了
#leaf
節點保持着對它的父節點(parentNode)的引用,這樣一直遞歸引用了#tree
節點,因此只有當leafRef
被設置成null後,#tree
下面的整個樹節點纔有可能被垃圾回收器回收。
該工具是能夠幫助你追蹤JS堆裏面的內存泄漏的另外一大利器。
選中Record Allocation Timeline按鈕,點擊Start按鈕以後,執行你認爲可能會引發內存泄漏的操做,操做以後點擊左上角的中止按鈕便可。你能夠在藍色豎線上經過縮放來過濾構造器窗格來僅僅顯示在指定的時間幀內的被分配的對象。
錄製過程當中,在時間線上會出現一些藍色豎條,這些藍色豎條表明一個新的內存分配,這個新的內存分配均可以會有潛在的內存泄露問題。
經過展開對象並點擊它的值則能夠在Object窗格中查看更多新分配的對象細節。
從JS函數角度記錄並查看內存的分配信息。點擊Start按鈕,執行你想要去深刻分析的頁面操做,當你完成你的操做後點擊Stop按鈕。而後會顯示一個按JS函數進行內存分配的分解圖,默認的視圖是Heavy (Bottom Up),該視圖會把最消耗內存的函數顯示在最頂端。
下圖是切換到Chart視圖時具體的界面,點擊任意函數跳轉到Sources面板能夠查看具體的函數信息。