【理解chrome開發者工具】 part2 網絡,性能與內存

網絡 Network

瀑布流

隨着網頁的加載,每一個HTTP請求都會是瀑布流中的一條。第一條都是文件document的加載,當文件被解析,隨後一般是CSS文件的加載。和寫在HTML文件中的標籤中的順序是同樣的。但瀏覽器會作一些優化,好比會下降圖片的優先度,提高CSS文件的優先度等。web

在瀑布流下方的表格中,咱們能夠看到請求的Name,Status,Type等信息。Initiator列的意思是,什麼文件需求加載了這一行的文件。按住Shift點擊表格的一行,調用該行文件的相應文件會變綠(who called it?),該行文件調用的相應行會變紅(who does it called?)。chrome

瀑布流顏色

  • 白色 隊列中。不常見。HTTP1中,瀏覽器一次性只能進行6個TCP鏈接,好比咱們有7個CSS文件,那麼其中的一個就會在隊列中。
  • 灰色 一個請求能發送前的各類停滯反應時間。
  • 淺灰色 在Proxy代理服務器消耗的時間
  • 深綠色 DNS查找的時間
  • 橙色 創建鏈接時間。包括TCP握手時間和創建SSL鏈接時間。
  • 棕色 SSL鏈接時間
  • 綠色 等待回覆的時間。也就是等待得到第一個字節的時間。若是綠色很長說明應用服務器很慢。
  • 藍色 下載回覆內容的時間。和文件大小有關係。

快照

若是咱們點擊Capture Screenshot按鈕,從新加載頁面, 就能夠看到網頁的每次repaint,也就是網頁是如何加載的。瀏覽器

使用這個功能,咱們能夠知道在慢速網絡下,網頁是如何呈現出來的。服務器

過濾信息

Network面板中,咱們能夠點擊文件類型來查看特定類型的文件。左側有個輸入框也能夠輸入特定條件。好比larger-than:200px,就能夠觀察大於200px的圖片請求。網絡

Disable Cache,Offline,Preserve Log三個按鈕的功能是顯而易見的。chrome-devtools

性能 Performance

開發者性能VS用戶端性能測試

開發者性能測試是在開發環境中作性能測試,可是用戶端是在真實用戶使用的狀況下記錄測試數據。之前是這麼作的:函數

const start = new Date().getTime();

const end = new Date().getTime();

const time = end - start;

這樣咱們就能夠記錄下用戶做出一個操做的時間,而後將數據post回來。工具

後來有了Performance API:oop

performance.mark('start')

performance.mark('end);

performance.measure('Our Measurement,'start','end');

performance.getEntriesByType('measure')

圖片性能

通常圖片過大的解決方法:佈局

  • resize圖片
  • 刪除圖片的meta data
  • 在服務器端使用gzip,brotli, zopfli等工具。

還有一個HTML API要知道,srcset
能夠在不一樣窗口大小的時候加載指定的圖片。

<img srcset="small.jpg  300w,
              medium.jpg 800w,
              large.jpg 1200w">

可是爲了瀏覽器兼容性,咱們老是應該給默認的src attribute留一個URL。

頁面卡頓 Page Jank

爲何看起來卡

現代大多數屏幕刷新率都是60幀每秒。1秒/60 = 16.66毫秒。因此咱們的一個畫面更新的處理時間若是超過了16毫秒,就感受卡。

編譯時間慢

有一種卡的緣由是由於,解析Javascript的時間過長。V8引擎渲染頁面的時候,須要編譯Javascript,生成AST(Abstract Syntax Tree)。當客戶端的處理性能不好的時候,就要等好久。

佈局抖動

還有一種卡的緣由是由於,Layout thrashing,反覆佈局,又稱佈局抖動。

//Read
const h1 = element.clientHeight;
//Write
element1.style.height = (h1 * 2) + 'px';
//Read
const h2 = element2.clientHeight;
//Write
element2.sytle.height = (h2 * 2) + 'px';

當咱們反覆進行這種DOM讀寫操做的時候,就會形成佈局抖動。

requestAnimationFrame

若是咱們能夠將讀和寫徹底分開,一次性操做全部讀,一次性操做全部寫,就不會有這種狀況,可是這是不現實的。這就是使用window.requestAnimationFrame()的緣由。

簡單說requestAnimationFrame將讀寫操做和屏幕刷新率匹配起來,當瀏覽器準備好更新下一幀時,作想作的操做,減小性能浪費,避免跳幀。關於這個話題有不少寫Event Loop的文章裏也有寫,這裏很少寫。

觀察頁面重繪狀況

在開發者工具中,咱們在更多工具中能夠找到Rendering的選項。

圖片描述

打開這個選項,頁面每次repaint的地方都會變成綠色,幫助開發者觀察是否一些不必重繪的地方在不停的被重繪,浪費性能。

錄製操做和分析

咱們點擊錄製按鈕,在頁面上作一些操做,好比Scroll。Performance面板中就會有一些數據。
圖片描述

最下方有一個餅狀圖是一個歸納總結。

展開Main行,X軸表明處理時間,Y軸是Call Stack。Y軸高不要緊,只是函數之間不斷的調用,可是若是有色塊很寬的話就說明處理時間很長。

咱們可使用WASD來操做。按W Zoom In能夠看到具體信息。

找到一個很寬的色塊,看以前是哪一個色塊調用了這個色塊,而後咱們就能夠在下方Summary面板中找到具體文件名,點擊去Sources面板看代碼。

內存 Memory

JS中的內存泄漏

當一些內存沒有按開發者的意願被釋放的時候,就出現了內存泄漏。

常見的內存泄漏狀況

  • 意外添加的全局變量
function foo() {
  bar = "Hi"
}

當foo被調用的時候,由於bar沒有變量聲明關鍵詞const, var, let。JS就會一直向上找這個變量到全局做用域,而後會爲你建立一個全局變量bar。當這個函數結束的時候,你覺得這個bar會被回收,但其實它一直留在全局。設想若是這個bar不是「Hi」而是一個擁有不少元素的array,它留在了全局做用域,這並非咱們想要的狀況。

  • 沒有取消的計時器

顧名思義,計時器沒有被取消或移除。

  • 多餘的DOM元素變量
const button = document.getElementById('button);

document.body.removeChild(
  document.getElementById('button)
);
}

這裏咱們在DOM中移除了這個button,可是以前指向這個元素的reference還在,就是變量button。因此這個reference就留在了內存中。

發現內存泄漏

打開Chrome的任務管理器,確保Javascript Memory列有顯示。咱們能夠看到每一個標籤頁的內存使用狀況。若是有一個標籤頁的內存使用不穩定,一直在上升,說明出現了內存泄漏。

在Performance面板記錄下的數據中,若是咱們打勾Memory選項,咱們就能夠看到Memory行。若是線圖不停的上升,就說明出現了內存泄漏。

定位內存泄漏

在開發者工具的Memory面板中,咱們能夠選擇Heap Snapshot,記錄一個當前頁面具體內存使用狀況的快照。注意Shallow Size列和Retained Size列。

Shallow Size是對象自身佔用內存的大小,而Retained Size是指咱們移除Object後能得到多少空間,也就是將對象自己和連同的相關對象一塊兒刪除後釋放的內存大小。好比一個變量指向一個很大的Object,這個變量自己是個reference很小(Shallow Size很小),可是移除這個變量之後,咱們就能夠得到很大的空間(Retained Size很大)。

咱們能夠根據Shallow Size給Heap Snapshot排序,找到佔用內存最多的對象,若是不確認是不是內存泄漏,能夠再記錄一個Heap Snapshot作對比。若是該對象的Shallow Size增加了,說明確實出現了內存泄漏。咱們能夠根據工具給的提示信息,找到開發代碼片斷作修改。

評估 Audit

如今的Audit面板整合了谷歌的Lighthouse服務。網上還有一些其餘不錯的第三方服務如webpagetest, sonarwhal。

官方文檔
Chrome Developer Tool

相關文章
相關標籤/搜索