1. 程式人生 > >Chrome開發者工具不完全指南(四、效能進階篇)

Chrome開發者工具不完全指南(四、效能進階篇)

前言

  Profiles面板功能的作用主要是監控網頁中各種方法執行時間和記憶體的變化,簡單來說它就是Timeline的數字化版本。它的功能選項卡不是很多(只有三個),操作起來比較前面的幾塊功能版本來說簡單,但是裡面的資料確很多,很雜,要弄懂它們需要花費一些時間。尤其是在記憶體快照中的各種龐雜的資料。在這篇部落格中滷煮將繼續給大家分享Chrome開發者工具的使用經驗。如果你遇到不懂的地方或者有不對的地方,可以在評論中回覆滷煮,文章最後滷煮會最後把祕籍交出來。下面要介紹的是Profiles。首先開啟Profiles面板。



  Profiles介面分為左右兩個區域,左邊區域是放檔案的區域,右邊是展示資料的區域。在開始檢測之前可以看到右邊區域有三個選項,它們分別代表者不同的功能:


    1.(Collect JavaScript CPU Profile)監控函式執行期花費的時間
    2.(Take Heap Snapshot)為當前介面拍一個記憶體快照
    3.(Record Heap Allocations)實時監控記錄記憶體變化(物件分配跟蹤)

一、Collect JavaScript CPU Profile(函式收集器)

  首先來關注第一個功能,(Collect JavaScript CPU Profile)監控函式執行期花費的時間。講道理不如舉例子,為了更清楚地瞭解它的功能概況,我們可以編寫一個測試列子來觀察它們的作用。這個列子簡單一些,使得我們分析的資料更清晰一些。

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<button id="btn"> click me</button>
<script type="text/javascript">
function a() {
console.log('hello world');
}

function b() {
a();
}

function c() {
b();
}

document.getElementById(
'btn').addEventListener('click', c, true); </script> </body> </html>

  在右邊區域中選擇Collect JavaScript CPU Profile 選項,點選下方的Start按鈕(也可以點選左邊的黑色圓圈),這時候Chrome會開始記錄網頁的方法執行,然後我們點選介面的按鈕來執行函式。最後再點選右邊區域的Stop按鈕(或者左邊的紅色圓圈),這時監控就結束了。左邊Profiles會列出一個檔案,單擊可以看到如下介面:

  生存了一個數據表格,它們的意義在上圖中已經標記出來了。它記錄的是函式執行的時間以及函式執行的順序。通過右邊區域的型別選項可以切換資料顯示的方式。有正包含關係,逆包含關係,圖表型別三種選項。我們可以選擇其中的圖表型別:


  可以看到這個面板似曾相識,沒錯,它跟之前的TimeLine面板很像,的確,雖然很像,但功能不一樣,不然也就沒必要重複做了。從上圖可以看到點選按鈕執行的各個函式執行的時間,順序,包含關係和CUP變化等。你可以在生成檔案之後在左邊區域中儲存該檔案記錄,下次只需要在區域2這中點選load按鈕便可以加載出來。也就是說你可以本地永久地記錄該段時間內的方法執行時間。第一個功能大概就這麼多,比較其他兩個來說簡單。

二、Take Heap Snapshot(記憶體快照

  下面我們來介紹一下第二個功能的用法。第二個功能是給當前網頁拍一個記憶體快照.選擇第二個拍照功能,按下 Take Snapshot 按鈕,給當前的網頁拍下一個記憶體快照,得到如下圖。

  可以看到左邊區域生成個檔案,檔名下方有數字,表示這個張快照記錄到的記憶體大小(此時為3.2M)。右邊區域是個列表,它分為五列,表頭可以按照數值大小手動排序。在這張表格中列出的一些列數字和標識,以及表頭的意義比較複雜,涉及到一些js和記憶體的知識,我們就先從這些表頭開始瞭解他們。從左到右的順序它們分別表示:
  Constructor(建構函式)表示所有通過該建構函式生成的物件
  Distance 物件到達GC根的最短距離
  Objects Count 物件的例項數
  Shallow size 對應建構函式生成的物件的shallow sizes(直接佔用記憶體)總數
  Retained size 展示了對應物件所佔用的最大記憶體
  CG根!是神馬東西?在google的官方文件中的建議是CG根不必用到開發者去關心。但是我們在這裡可以簡單說明一下。大家都知道js物件可以互相引用,在某個物件申請了一塊記憶體後,它很可能會被其他物件應用,而其他物件又被另外的物件應用,一層一層,但它們的指標都是指向同一塊記憶體的,我們把這最初引用的那塊記憶體就可以成為GC根。用程式碼表示是這樣的:

var obj = {a:1};
obj.pro = { a : 100 };
obj.pro.pro = { b : 200 };
var two = obj.pro.pro;
//這種情況下 {b:200} 就是被two引用到了,{b:200}物件引用的記憶體就是CG根


  用一張官方的圖可以如下表示:



  構成這張關係網的元素有兩種:
  Nodes:節點,對應一個物件,用建立該物件的構造方法來命名
  Edges:連線線,對應著物件間的引用關係,用物件屬性名來命名
  從上圖你也可以看到了第二列的表頭Dishtance的意義是什麼,沒錯,它指的就是CG根和引用物件之間的距離。根據這條解釋,圖中的物件5到CG根的距離就是2!那麼什麼是直接佔用記憶體(Shallow size)和最大佔用記憶體(Retained size)呢?直接佔用記憶體指的是物件本身佔用的記憶體,因為物件在記憶體中會通過兩種方式存在著,一種是被一個別的物件保留(我們可以說這個物件依賴別的物件)或者被Dom物件這樣的原生物件隱含保留。在這裡直接佔有記憶體指的就是前一種。(通常來講,陣列和字串會保留更多的直接佔有記憶體)。而最大記憶體(Retained size)就是該物件依賴的其他物件所佔用的記憶體。你要明白這些都是官方的解釋,所以即使你覺得雲裡霧裡也是正常的,官方解釋肯定是官腔嘛。按照滷煮自己的理解是這樣的:

function a() {
    var obj = [1,2,.......n];
    return function() {
        //js作用域的原因,在此閉包執行的上下文中可以訪問到obj這個物件
        console.log(obj);
    }
}
//正常情況下,a函式執行完畢 obj佔用的記憶體會被回收,但是此處a函式返回了一個函式表示式(見Tom大叔的部落格函式表示式和函式宣告),其中obj因為js的作用域的特殊性一直存在,所以我們可以說b引用了obj。
var b = a();
//每次執行b函式的時候都可以訪問到obj,說明記憶體未被回收 所以對於obj來說直接佔用記憶體[1,2,....n], 而b依賴obj,所obj是b的最大記憶體。
b()

  在dom中也存在著引用關係:我們通過程式碼來看下這種引用關係:

<html>
    <body>
        <div id="refA">
            <ul>
                <li><a></a></li>
                <li><a></a></li>
                <li><a id="#refB"></a></li>
            </ul>
        </div>
        <div></div>
        <div></div>
    </body>
</html>


<script>
    var refA = document.getElementById('refA');
    var refB = document.getElementById('refB');//refB引用了refA。它們之間是dom樹父節點和子節點的關係。
</script>

  現在,問題來了,如果我現在在dom中移除div#refA會怎麼樣呢?答案是dom記憶體依然存在,因為它被js引用。那麼我把refA變數置為null呢?答案是記憶體依然存在了。因為refB對refA存在引用,所以除非在把refB釋放,否則dom節點記憶體會一直存在瀏覽器中無法被回收掉。上圖:

  

  所以你看到Constructor這一列中物件如果有紅色背景就表示有可能被JavaScript引用到但是沒有被回收。以上只是滷煮個人理解,如果不對頭,請你一定要提醒滷煮好即時更新,免得誤人子弟!接著上文,Objects Count這一列是什麼意思呢?Objects Count這一列的意義比較好理解,從字面上我們就知道了其意義。就是物件例項化的數量。用程式碼表示就是這樣的:

var ConstructorFunction = function() {};//建構函式
var a = new ConstructorFunction();//第一個例項
var b = new ConstructorFunction();//第二個例項
.......
var n = new ConstructorFunction();//第n個例項


  可以看到建構函式在上面有n個例項,那麼對應在Objects Count這列裡面就會有數字n。在這裡,ConstructorFunction是我們自己定義的建構函式。那麼這些建構函式在哪裡呢,聰明的你一定可以猜到就在第一列Constructor中。實際上你可以看到列表中的Constructor這一列,其中多數都是系統級別的建構函式,有一部分也是我們自己編寫的:

  global property - 全域性物件(像 ‘window’)和引用它的物件之間的中間物件。如果一個物件由建構函式Person生成並被全域性物件引用,那麼引用路徑就是這樣的:[global] > (global property > Person。這跟一般的直接引用彼此的物件不一樣。我們用中間物件是有效能方面的原因,全域性物件改變會很頻繁,非全域性變數的屬性訪問優化對全域性變數來說並不適用。
  roots - constructor中roots的內容引用它所選中的物件。它們也可以是由引擎自主建立的一些引用。這個引擎有用於引用物件的快取,但是這些引用不會阻止引用物件被回收,所以它們不是真正的強引用(FIXME)。
  closure - 一些函式閉包中的一組物件的引用
  array, string, number, regexp - 一組屬性引用了Array,String,Number或正則表示式的物件型別
  compiled code - 簡單來說,所有東西都與compoled code有關。Script像一個函式,但其實對應了<script>的內容。SharedFunctionInfos (SFI)是函式和compiled code之間的物件。函式通常有內容,而SFIS沒有(FIXME)。
HTMLDivElement, HTMLAnchorElement, DocumentFragment 等 – 你程式碼中對elements或document物件的引用。

  點選展開它們檢視詳細項,@符號表示該物件ID。:

  一個快照可以有多個試圖,在左邊區域的右上角我們可以看到點選下拉選單可以得到四個個任務檢視選項:

他們分別代表:
  Summary(概要) - 通過建構函式名分類顯示物件;
  Comparison(對照) - 顯示兩個快照間物件的差異;
  Containment(控制) - 探測堆內容;
  Statistic(圖形表)-用圖表的方式瀏覽記憶體使用概要Comparison是指對比快照之間的差異,你可以首先拍一個快照A,操作網頁一段時間後拍下另外一個快照B,然後在B快照的右邊距區域的左上角選擇該選項。然後就可以看到對比圖。上面顯示的是每個列,每一項的變化。在對照檢視下,兩個快照之間的不同就會展現出來了。當展開一個總類目後,增加和刪除了的物件就顯示出來了:


嘗試一下官方示例幫助你瞭解對比的功能。
  你也可以嘗試著檢視Statistic選項,它會以圖表的方式描述記憶體概況。

三、Record Heap Allocations.(物件跟蹤器)

  好了,第二個功能也介紹完了,最後讓我們來瞧瞧最後一個功能Record Heap Allocations.這個功能是幹啥的呢。它的作用是為為我們拍下一系列的快照(頻率為50ms),為我們檢測在啟用它的時候每個物件的生存情況。形象一點說就是假如拍攝記憶體快照的功能是照相那麼它功能相當於錄影。當我們啟用start按鈕的時候它便開始錄影,直到結束。你會看到左側區域上半部分有一些藍色和灰色的柱條。灰色的表示你監控這段時間內活躍過的物件,但是被回收掉了。藍色的表示依舊沒有沒回收。你依舊可以滑動滾輪縮放時間軸。

  物件跟蹤器功能的好處在於你可以連續不斷的跟蹤物件,在結束時,你可以選擇某個時間段內(比如說藍色條沒有變灰)檢視期間活躍的物件。幫助你定位記憶體洩露問題。

四、結束 

 好了,差不多把Profiles講完了。這東西對我們查詢記憶體洩露來說還是蠻有作用的。對於工具來說,主要是多用,熟能生巧嘛。如果你覺得不過癮,我推薦你去閱讀官方文件,裡面有N多的例子,N多的說明,非常詳細。前提是你能跳到牆外去。當然也有翻譯文件(滷煮的祕籍都給你了,推薦一下吧)。最後真的是要像一片文章裡面寫的一樣“感謝發明計算機的人,讓我們這些剪刀加漿糊的學術土匪變成了複製加貼上版的學術海盜。”下期是ConsoleAudits。敬請關注。

相關推薦

Chrome開發者工具完全指南效能

前言   Profiles面板功能的作用主要是監控網頁中各種方法執行時間和記憶體的變化,簡單來說它就是Timeline的數字化版本。它的功能選項卡不是很多(只有三個),操作起來比較前面的幾塊功能版本來說簡單,但是裡面的資料確很多,很雜,要弄懂它們需要花費一些時間。尤其是在記憶體快照中的各種龐雜的資料。在這篇

Chrome開發者工具完全指南移動

  前面介紹了Chrome開發者工具的大部分內容工具,現在介紹最後兩塊功能Audits和Console面板。一、Audits  Audits面板會針對目前網頁提出若干條優化的建議,這些建議分為兩大類,一類是網路載入效能,另一類是介面效能。首先開下它的主介面。  Audits面板的網路優化建議參照的是雅虎前端工

Chrome開發者工具完全指南基礎功能

  就算你不是一名前端開發工程師,相信你也不會對Chrome瀏覽器感到陌生。根據最新的一份(2015/06)的瀏覽器市場佔有率報告,Chrome近乎佔有瀏覽器天下的半壁江山。簡單、快捷使它成為了新時代人們的新寵。如果你是一名web開發人員,我推薦你使用Chrome。作為前端開發的"IDE",你只需要搭配一個編

Chrome開發者工具完全指南

function a () { b(); } function b() { c(); } function c() { //在該處斷點,檢視call stack } a->b->c. call stack 從上到下的順序就是 c

Chrome開發者工具完全指南效能

<!DOCTYPE html> <html> <head> <title></title> <style type="text/css"> div{ height: 20px; widows: 20p

ctf工具完全指南

最近接連趕上了ssctf和hctf,對我來說算是一償夙願,總算從在網站上做做以前的題,到參加比賽,正式邁入圈內了。雖然學校內的氛圍不濃厚,但總算也能拉起一支能參賽的隊伍,第一次正式參賽的結果算是讓我挺滿意的。戰後是時候來個總結了。 經驗上的差距讓一些本來可以做的題目也

更效率更優雅 | 阿里巴巴開發者工具完全盤點

從人工到自動化,從重複到創新,技術演進的歷程中,伴隨著開發者工具類產品的發展。 阿里巴巴將自身在各類業務場景下的技術積澱,通過開

Spring Data REST完全指南

上一篇文章介紹了Spring Data REST的功能及特徵,以及演示瞭如何在專案中引入Spring Data REST並簡單地啟動演示了Spring Data REST專案。在本文中,我們將深入瞭解Spring Data REST的特性,以此來滿足我們日常api開發工作的要求。 如果僅僅是上一篇文章中對Sp

Spring Data REST完全指南

上一篇我們介紹了使用Spring Data REST時的一些高階特性,以及使用程式碼演示瞭如何使用這些高階的特性。本文將繼續講解前面我們列出來的七個高階特性中的後四個。至此,這些特效能滿足我們大部分的介面開發場景。 需要滿足的一些要求: 1.針對欄位級別,方法級別,類級別進行限制(禁止某些欄位,方法,介面的

Android資源res之向量圖完全指南附贈SVG-path命令分析

零、前言 第一次接觸SVG時,被它的強大折服,下面兩個小例子可以看看 SVG 文字sin型曲線動畫、SVG繪製星空效果 Android5.0+也支援向量圖VectorDrawable,是變異削弱版的SVG,但已經非常強大了 本來不想寫SVG的path的,但是發現需要用到,還是總結一下吧 留圖

Hadoop完全分佈單機偽分佈模式搭建

一,配置一臺普通的虛擬機器 二、解壓安裝Hadoop 三、配置Java與Hadoop的環境變數 鍵入命令: vim /etc/profile 按i進入插入狀態 ,開始使用vim編輯器編輯: 在末尾插入下列這段程式碼: export JAVA_HOME='

EF6 在原有數據庫中使用 CodeFirst 總復習新建實體對象

block clear 數據庫 chang 添加 優先 數據遷移 ons hang 在原有數據庫中使用 CodeFirst ,除了第一次添加實體後要立即執行一次 Enable-Migrations add-migration Initial -IgnoreChan

iOS開發者如何在枯燥的工作中尋求技術的提升

調用 loaded 剛才 高可用 package 如果 sql 讀寫 大牛 技術成長是很多同學面臨的問題,一些工作了幾年的同學會遇到成長瓶頸,覺得自己進步緩慢,無論是公司業務的原因還是個人原因,覺得自己的技術水平得不到成長了。或者一些剛工作沒多久的同學和在找工作的同學,都想

spring cloud路由閘道器

Zuul的主要功能是路由轉發和過濾器。路由功能是微服務的一部分,比如/api/user轉發到到user服務,/api/shop轉發到到shop服務。zuul預設和Ribbon結合實現了負載均衡的功能。 一、路由功能 1.建立service-zuul專案 2.引入Eureka Server

Hadoop學習記錄hadoop實現檔案操作

1.從Hadoop URL讀取資料 類似cat命令 public class URLCat { static{ URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory()); }

無業務伸縮之二,雲監控搭配SLB及ESS

雲端計算ESS彈性伸縮課程 無業務不伸縮之二,雲監控搭配SLB及ESS(進階篇) 連載雲端計算文章主題 後續的連載如下1、 無業務不伸縮之一,雲端計算有ESS2、 無業務不伸縮之二,雲監控搭配SLB及ESS3、無互動不加速,雲端計算有CDN4、無對像不儲存,雲端計算有OSS5、無檔案不儲存,雲端計算有”

Spark修煉之道——Spark入門到精通:第十節 Spark Streaming 快取Checkpoint機制

作者:周志湖 微訊號:zhouzhihubeyond 主要內容 Spark Stream 快取 Checkpoint 案例 1. Spark Stream 快取 通過前面一系列的課程介紹,我們知道DStream是由一系列的RDD構成的,

Redis使用總結處理延時任務

引言在開發中,往往會遇到一些關於延時任務的需求。例如生成訂單30分鐘未支付,則自動取消生成訂單60秒後,給使用者發簡訊對上述的任務,我們給一個專業的名字來形容,那就是延時任務。那麼這裡就會產生一個問題,這個延時任務和定時任務的區別究竟在哪裡呢?一共有如下幾點區別定時任務有明確

c# MEF框架 MEF高階

轉自:http://www.cnblogs.com/yunfeifei/p/3991330.html 好久沒有寫部落格了,今天抽空繼續寫MEF系列的文章。有園友提出這種系列的文章要做個目錄,看起來方便,所以就抽空做了一個,放到每篇文章的最後。 前面四篇講了MEF的基礎

Mysql 入門,增刪改查

bsp com pre sco height name 數據 mysql from 主要已以下兩個表students與students_score,進行數據的增刪改查操作! 1、SELECT 1)select id,tel from students