效能優化篇 - Performance(工具 & api)

熱情的劉大爺發表於2019-03-21

前言

Performance 一個在前端開發領域中,無法被忽視的存在,如果我們的開發是一個滿足需求就可以的產品,那麼可能就用不到它;但是如果我們想對我們的這個產品,做一個極致的優化,那麼 Performance 是一個很好的選擇,也是一個不容忽視的選擇。

Performance 工具 和 api 的優缺點

Performance 工具 優點:

  • 視覺化圖形介面
  • 每毫秒做的事情
  • 檔案的執行載入的順序
  • 每毫秒介面展示的效果
  • 每個方法執行的順序和時間(由下至上)
  • 倒置的事件火焰圖(由下至上)
  • 資料總結

Performance 工具 缺點:

  • 無法檢視某一個區間之內的執行時間
  • 無法檢視 js 堆的大小使用情況及限制
  • 無法檢視頁面是重新整理還是載入,重定向次數
  • 無法檢視什麼時間開始做的效能測試
  • 可以在資源快取已滿的時候進行回撥處理
  • 設定瀏覽器應在其效能條目緩衝區中儲存的最大效能條目物件數

Performance api 優點:

  • 完全彌補了 Performance 工具 的缺點,還可以讓我們通過資料的方式去知道具體的時間

Performance api 缺點:

  • 無法像 Performance 工具 那樣圖形化的去檢視資料資訊

大致的介紹了一下工具和api的優缺點,其實很明顯的可以看出來,它們是相輔相成的,其實在一般的工具當中,我們會使用其中的某一個去進行效能的優化,但是對於一個想要進行真正的,徹底性的效能優化,還是需要兩者之間的配合,去進行更高效、更系統、更全面的優化。

Performance 工具

效能優化篇 - Performance(工具 & api)

這就是 Performance 工具 的介面。

效能優化篇 - Performance(工具 & api)

  • 上下箭頭,就是用來上傳和下載每一次效能檢測報告的;
  • no recordings 就是每一次的檢測報告,可以根據每一次的檢測報告,去進行效能優化的對比;
  • Screenshots 是用來檢視在每個時間段介面的變化;
  • Memory 儲存呼叫棧的大小,在不同時間段的不同大小;

效能優化篇 - Performance(工具 & api)

  • Disable Javascript samples 禁用 javascript 呼叫棧,在後面講解 Main 部分進行詳解;
  • Enable advanced paint instrumentation (slow) 記錄渲染事件的細節;
  • Network 用來修改檢測在不同的網路環境下,介面的渲染;
  • CPU 用來檢視電腦的效能問題;

到這裡呢,簡單的介紹了一下上面幾個按鈕真正的意義,下面結合視覺化的圖表在配上面這些按鈕進行效能的檢測:

效能優化篇 - Performance(工具 & api)

這個效能檢測是對掘金網站 --> 我的主頁做的效能優化檢測截圖

第一部分:概覽

這裡最主要是整體的介面渲染的時候,每個時間段執行的事件順序,通過上圖,我們就能知道我們每個時間段(精確到毫秒)都做了什麼,當滑鼠放上去的時候,我們還可以大圖的形式去檢視我們每個時間段介面的渲染情況:

效能優化篇 - Performance(工具 & api)

當在這裡通過點選滑動到某一位置鬆開的時候,可以檢視某一個區間直接的一個渲染情況

第二部分:Network

效能優化篇 - Performance(工具 & api)
Network 這裡我們可以看出來,我們資源載入的一個順序情況,什麼時間載入了什麼資源,通過這裡,我們更直觀的可以知道,資源是並行載入的

第三部分:Frames

效能優化篇 - Performance(工具 & api)

Frames 這裡,其實就是檢視我們在什麼時間,介面發生了改變,它和第一部分的區別就是在介面沒有改變的時候,它是不做記錄的,但是概覽部分是會做記錄的

第四部分: Interactions

效能優化篇 - Performance(工具 & api)

在我看過的文章裡,很少看到會有這部分,是因為在不適用一些互動動作的時候,是不會有這部分的功能的,從這裡我們看到了掘金使用了一些動畫的動作

第五部分:Timings

效能優化篇 - Performance(工具 & api)

這張圖不是掘金官網的,因為在專案打包後,就沒有對應的事件呼叫,所以線上上經過打包的網站,是看不到這部分的

第六部分:Main

效能優化篇 - Performance(工具 & api)

這裡就是 Performance 工具 當中比較核心的一部分,俗稱 火焰圖 , 這裡是一個由下而上的事件執行圖,你可以簡單的理解成上面這是一個彙總

第七部分:Raster

效能優化篇 - Performance(工具 & api)

通過這裡,我們知道掘金官網,在前端部分一共使用了幾條執行緒

這裡有一個知識點,這裡是指瀏覽器渲染的執行緒,而不是js的執行緒,特此宣告一下,怕被有的同學拿js單執行緒來噴我?
複製程式碼

第八部分: GPU

效能優化篇 - Performance(工具 & api)

這裡我們可以很清楚的看出來,網站在什麼時間有 GPU 加速

第九部分:taskSchedulerForegroundBlockingWorker

效能優化篇 - Performance(工具 & api)

任務計劃程式前臺阻止工作程式,這裡我用的很少,也是第一次見,等的我明確一下這裡是做什麼的,在進行更新,如果有知道的朋友,也可以評論告訴我,我及時進行改進

第十部分:Memory

效能優化篇 - Performance(工具 & api)

上面有提到 Memory 選項,在勾選後,就會顯示該事件折線圖,通過該圖,可以看出我們在不同的時間段,不同事件的執行情況

第十一部分:效能檢測詳情

效能優化篇 - Performance(工具 & api)

上面有4個標籤:Summary(效能摘要)Bottom-Up(事件列表,由下至上,對應 Main 火焰圖)Call Tree(每個事件的子項資訊)Event log(事件日誌)

接下來,我們依次詳解

Summary(效能摘要)

其實我們一看就明白,它是一個用來統計在我們檢測效能的時間範圍內,都做了哪些事情:

  • Loading :載入時間
  • Scripting :js計算時間
  • Rendering :渲染時間
  • Painting :繪製時間
  • Other :其他時間
  • Idle :瀏覽器閒置時間

Bottom-Up(事件列表)

效能優化篇 - Performance(工具 & api)

這裡和 Main 裡面看見的,其實是一個對應著的關係,從這裡,我們可以看見所有的事件列表,還有每個事件的 Self Time(自己呼叫的時間)Total Time(總呼叫時間,包括子項呼叫時間)Activity(行為,包括呼叫該事件的位置)

Call Tree(事件子項資訊)

效能優化篇 - Performance(工具 & api)

其實這裡和 Bottom-Up 部分是一樣的,就不做太多的說明了,大家看一下就知道了

Event Log(事件日誌)

效能優化篇 - Performance(工具 & api)

這裡比前面的 Bottom-UpCall Tree 相比,多了一個 Start Time 屬性,這個屬性其實就是開始的時間,從什麼時間開始執行的什麼事件

到這裡,有關 Performance 工具 的介紹,就到了這裡了,如果有什麼解釋不清楚的,或者有問題的地方,還請大家評論指出,我做及時的更正

下面,給大家介紹 Performance Api

Performance API

Performance 用來獲取當前頁面的效能資訊,它和 Performance 工具 的區別在上面我們已經寫出來了,就不在這裡囉嗦了

注意:除了以下指出的情況外,該介面及其成員在 Web Worker 中可用。
此外,還需注意,performance 的建立和衡量都是同一環境下的。
即,如果你在主執行緒(或者其他 worker)中建立了一個 performance,那麼它在另外的 worker 執行緒中是不可用的;反之亦然。
複製程式碼

接下來,我們先介紹一下 Performance API 的屬性:


Performance.navigation(操作相關)

該屬性是一個物件,有兩個屬性值,分別是 redirectCount(重定向次數)type(操作的型別)

redirectCount

該屬性值為幾,就說明了當前頁面重定向了多少次;

type

type(0):當前頁面是通過點選連結,書籤和表單提交,或者指令碼操作,或者在url中直接輸入地址;

type(1):點選重新整理頁面按鈕或者通過Location.reload()方法顯示的頁面;

type(2):頁面通過歷史記錄和前進後退訪問時;

type(255):任何其他方式


Performance.timing(延遲相關)

當前頁面中與時間相關的資訊:

navigationStart

從同一個瀏覽器的上一個頁面解除安裝 unload 結束時的時間戳(精確到毫秒)

unloadEventStart

unload 事件執行時的時間戳。如果沒有上一個頁面,或者如果先前的頁面或所需的重定向之一不是同一個來源, 這個值會返回0

unloadEventEnd

unload 事件執行完的時間戳。如果沒有上一個頁面,或者如果先前的頁面或所需的重定向之一不是同一個來源, 這個值會返回0

redirectStart

第一個HTTP重定向開始時得時間戳。如果沒有上一個頁面,或者如果先前的頁面或所需的重定向之一不是同一個來源, 這個值會返回0

redirectEnd

最後一個HTTP重定向完成時(也就是說是HTTP響應的最後一個位元組直接被收到的時間)的時間戳

fetchStart

表徵了瀏覽器準備好使用HTTP請求來獲取(fetch)文件的時間戳。這個時間點會在檢查任何應用快取之前

domainLookupStart

表徵了域名查詢開始的時間戳。如果使用了持續連線,或者這個資訊儲存到了快取或者本地資源上,這個值將和 PerformanceTiming.fetchStart 一致

domainLookupEnd

表徵了域名查詢結束的時間戳。如果使用了持續連線,或者這個資訊儲存到了快取或者本地資源上,這個值將和 PerformanceTiming.fetchStart 一致

connectStart

返回HTTP請求開始向伺服器傳送時的時間戳。如果使用持久連線,則返回值等同於 fetchStart 屬性的值

connectEnd

返回瀏覽器與伺服器之間的連線建立時的時間戳。如果建立的是持久連線,則返回值等同於 fetchStart 屬性的值。連線建立指的是所有握手和認證過程全部結束

secureConnectionStart

返回瀏覽器與伺服器開始安全連結的握手時的時間戳。如果當前網頁不要求安全連線,則返回0

requestStart

返回瀏覽器向伺服器發出HTTP請求時(或開始讀取本地快取時)的時間戳

responseStart

返回瀏覽器從伺服器收到(或從本地快取讀取)第一個位元組時的時間戳。如果傳輸層在開始請求之後失敗並且連線被重開,該屬性將會被數製成新的請求的相對應的發起時間

responseEnd

返回瀏覽器從伺服器收到(或從本地快取讀取,或從本地資源讀取)最後一個位元組時(如果在此之前HTTP連線已經關閉,則返回關閉時)的時間戳

domLoading

返回當前網頁DOM結構開始解析時(即 Document.readyState 屬性變為 loading 、相應的 readystatechange 事件觸發時)的時間戳

domInteractive

返回當前網頁DOM結構結束解析、開始載入內嵌資源時(即 Document.readyState 屬性變為 interactive 、相應的 readystatechange 事件觸發時)的時間戳

domContentLoadedEventStart

返回當解析器傳送 DOMContentLoaded 事件,即所有需要被執行的指令碼已經被解析時的時間戳

domContentLoadedEventEnd

返回當所有需要立即執行的指令碼已經被執行(不論執行順序)時的時間戳

domComplete

返回當前文件解析完成,即 Document.readyState 變為 complete 且相對應的 readystatechange 被觸發時的時間戳

loadEventStart

返回該頁面下,load 事件被髮送時的時間戳。如果這個事件還未被髮送,它的值將會是0

loadEventEnd

返回當 load 事件結束,即載入事件完成時的時間戳。如果這個事件還未被髮送,或者尚未完成,它的值將會是0


Performance.memory(js堆相關)

js堆有關的資訊:

jsHeapSizeLimit

js堆大小限制

totalJSHeapSize

js堆總大小

usedJSHeapSize

使用了js堆的大小


Performance.timeOrigin(效能檢測開始時間)

這個屬性返回的是效能測量開始時的時間的高精度時間戳,number 型別

Performance 還有一個事件:


Performance.onresourcetimingbufferfull(效能快取區已滿時回撥)

這個事件當瀏覽器的資源時間效能緩衝區已滿時會觸發

下面介紹一下 Performance 物件的方法:


Performance.clearMarks()

將給定的 mark 從瀏覽器的效能輸入緩衝區中移除


Performance.clearMeasures()

將給定的 measure 從瀏覽器的效能輸入緩衝區中


Performance.clearResourceTimings()

從瀏覽器的效能資料緩衝區中移除所有 entryTyperesourceperformance entries


Performance.getEntries(PerformanceEntryFilterOptions)

效能優化篇 - Performance(工具 & api)

PerformanceEntryFilterOptions 引數

可選引數,該引數是一個物件,可接受三個屬性:

  • nameperformance entry 的名字
  • entryTypeentry 型別. 合法的 entry 型別可以從 PerformanceEntry.entryType 方法獲取
  • initiatorType:初始化資源的型別,例如:xmlhttprequestotherscript

Performance.getEntries 返回值

Performance.getEntries(PerformanceEntryFilterOptions) 返回值陣列成員按 PerformanceEntry.startTime 時間順序排列

如果沒有符合 filter 條件的物件,那麼返回空陣列. 如果不帶任何引數,返回全部 entries

由於返回值是一個陣列,所以我們接下來講解一下每一個陣列項的每一個屬性的意思:

  • connectEnd:連線結束時間
  • connectStart:連線開始時間
  • decodedBodySize:解碼的主體大小
  • domCompletedom 渲染完成時間
  • domContentLoadedEventEnddom 內容載入事件結束時間
  • domContentLoadedEventStartdom 內容載入事件開始時間
  • domInteractivedom 互動時間
  • domainLookupEnd:域查詢結束時間
  • domainLookupStart:域查詢開始時間
  • duration:事件耗時
  • encodedBodySize:編碼主體大小
  • entryType:資源輸入型別
  • fetchStart:獲取資源開始時間
  • initiatorType:發起人型別
  • loadEventEnd:載入事件結束時間
  • loadEventStart:載入事件開始時間
  • name:這裡一般就是當前請求的 url 的地址
  • nextHopProtocol:下一個跳轉協議
  • redirectCount:重定向次數
  • redirectEnd:重定向開始時間,如果沒有重定向,值為0
  • redirectStart:重定向結束時間,如果沒有重定向,值為0
  • requestStart:請求開始時間
  • responseEnd:響應結束時間
  • responseStart:響應開始時間
  • secureConnectionStart:安全連線開始時間
  • serverTiming:伺服器時間
  • startTime:開始時間
  • transferSize:傳遞大小
  • type:該事件的型別
  • unloadEventEnd:解除安裝事件結束時間
  • unloadEventStart:解除安裝事件開始時間
  • workerStartworker 開始時間

Performance.mark(name)

根據給出 name 值,在瀏覽器的效能輸入緩衝區中建立一個相關的時間戳


Performance.measure(name, startMark, endMark)

這裡接收三個引數:

  • name:測量的名字
  • startMark:測量的開始標誌名字(也可以是 PerformanceTiming 屬性的名稱)
  • endMark:測量的結束標誌名字(也可以是 PerformanceTiming 屬性的名稱)

Performance.getEntriesByName(name, type)

這裡接收兩個引數:

  • name:測量的名字
  • type:測量的型別(frame, navigationresourcemarkmeasurepaint

Performance.getEntriesByType(type)

接收一個引數,type 同上面 Performance.getEntriesByName(name, type)type


Performance.now()

返回一個表示從效能測量時刻開始經過的毫秒數


Performance.setResourceTimingBufferSize(maxSize)

設定瀏覽器應在其效能條目緩衝區中儲存的最大效能條目物件數


Performance.toJSON()

返回 Performance 物件的 JSON 物件


Performance API 的介紹也差不多了,瀏覽器的相容性也是很不錯的:

效能優化篇 - Performance(工具 & api)

基本上在我們專案當中去做效能檢測是沒有問題的,畢竟我們是肯定不能把有關效能檢測的程式碼打包到專案當中

Performance API 的簡單使用

效能優化篇 - Performance(工具 & api)

這是我寫的一個小 demo ,大致的意思:

就是我們在定時器執行前,新增了個標記 measure-start

在定時器執行後,又新增了個標記 measure-end

測量一下兩個標記之間的開始時間和持續時間 measure-list

最後清除所有 marks 的標誌位和 measures 的標誌位;

從這個小 demo 我們就能看出來它的實用性和方便性,從這裡我們就可以看出來,Performance API 可以橫跨很多個方法,去檢測它的呼叫時間,而 Performance 工具 就沒有辦法做到這一點

這就是我所說的相輔相成的關鍵點所在

結束語

到這裡,基本上 Performance 工具Performance API 的差異還有各自功能的介紹,就寫的差不多了

從上面的講解我們可以瞭解到,不同的東西,做著不同的事情,雖然沒有誰都可以滿足部分需求,但是互相的配合,可以讓東西做到更好

文中如果有講解不詳細的地方,或者說有講解的內容有錯誤的地方,還請大家指出,方便我做最快的改正,感謝每一個認真看了文章看到這裡的朋友

下一篇文章,可能會有兩個選擇:

  • vue 和 react 通過 Performance 檢測到底誰的執行速度更快(精簡demo測試)
  • Audits 審計(精確到 Audits 審計報表檔案每一個欄位)

大家如果有什麼想法,還請留言,感謝大家支援

相關文章