前言
Performance
一個在前端開發領域中,無法被忽視的存在,如果我們的開發是一個滿足需求就可以的產品,那麼可能就用不到它;但是如果我們想對我們的這個產品,做一個極致的優化,那麼 Performance
是一個很好的選擇,也是一個不容忽視的選擇。
Performance 工具 和 api 的優缺點
Performance 工具
優點:
- 視覺化圖形介面
- 每毫秒做的事情
- 檔案的執行載入的順序
- 每毫秒介面展示的效果
- 每個方法執行的順序和時間(由下至上)
- 倒置的事件火焰圖(由下至上)
- 資料總結
Performance 工具
缺點:
- 無法檢視某一個區間之內的執行時間
- 無法檢視
js
堆的大小使用情況及限制 - 無法檢視頁面是重新整理還是載入,重定向次數
- 無法檢視什麼時間開始做的效能測試
- 可以在資源快取已滿的時候進行回撥處理
- 設定瀏覽器應在其效能條目緩衝區中儲存的最大效能條目物件數
Performance api
優點:
- 完全彌補了
Performance 工具
的缺點,還可以讓我們通過資料的方式去知道具體的時間
Performance api
缺點:
- 無法像
Performance 工具
那樣圖形化的去檢視資料資訊
大致的介紹了一下工具和api的優缺點,其實很明顯的可以看出來,它們是相輔相成的,其實在一般的工具當中,我們會使用其中的某一個去進行效能的優化,但是對於一個想要進行真正的,徹底性的效能優化,還是需要兩者之間的配合,去進行更高效、更系統、更全面的優化。
Performance 工具
這就是 Performance 工具
的介面。
- 上下箭頭,就是用來上傳和下載每一次效能檢測報告的;
no recordings
就是每一次的檢測報告,可以根據每一次的檢測報告,去進行效能優化的對比;Screenshots
是用來檢視在每個時間段介面的變化;Memory
儲存呼叫棧的大小,在不同時間段的不同大小;
Disable Javascript samples
禁用javascript
呼叫棧,在後面講解Main
部分進行詳解;Enable advanced paint instrumentation (slow)
記錄渲染事件的細節;Network
用來修改檢測在不同的網路環境下,介面的渲染;CPU
用來檢視電腦的效能問題;
到這裡呢,簡單的介紹了一下上面幾個按鈕真正的意義,下面結合視覺化的圖表在配上面這些按鈕進行效能的檢測:
這個效能檢測是對掘金網站 --> 我的主頁做的效能優化檢測截圖
第一部分:概覽
這裡最主要是整體的介面渲染的時候,每個時間段執行的事件順序,通過上圖,我們就能知道我們每個時間段(精確到毫秒)都做了什麼,當滑鼠放上去的時候,我們還可以大圖的形式去檢視我們每個時間段介面的渲染情況:
當在這裡通過點選滑動到某一位置鬆開的時候,可以檢視某一個區間直接的一個渲染情況
第二部分:Network
Network
這裡我們可以看出來,我們資源載入的一個順序情況,什麼時間載入了什麼資源,通過這裡,我們更直觀的可以知道,資源是並行載入的
第三部分:Frames
Frames
這裡,其實就是檢視我們在什麼時間,介面發生了改變,它和第一部分的區別就是在介面沒有改變的時候,它是不做記錄的,但是概覽部分是會做記錄的
第四部分: Interactions
在我看過的文章裡,很少看到會有這部分,是因為在不適用一些互動動作的時候,是不會有這部分的功能的,從這裡我們看到了掘金使用了一些動畫的動作
第五部分:Timings
這張圖不是掘金官網的,因為在專案打包後,就沒有對應的事件呼叫,所以線上上經過打包的網站,是看不到這部分的
第六部分:Main
這裡就是 Performance 工具
當中比較核心的一部分,俗稱 火焰圖 , 這裡是一個由下而上的事件執行圖,你可以簡單的理解成上面這是一個彙總
第七部分:Raster
通過這裡,我們知道掘金官網,在前端部分一共使用了幾條執行緒
這裡有一個知識點,這裡是指瀏覽器渲染的執行緒,而不是js的執行緒,特此宣告一下,怕被有的同學拿js單執行緒來噴我?
複製程式碼
第八部分: GPU
這裡我們可以很清楚的看出來,網站在什麼時間有 GPU
加速
第九部分:taskSchedulerForegroundBlockingWorker
任務計劃程式前臺阻止工作程式,這裡我用的很少,也是第一次見,等的我明確一下這裡是做什麼的,在進行更新,如果有知道的朋友,也可以評論告訴我,我及時進行改進
第十部分:Memory
上面有提到 Memory
選項,在勾選後,就會顯示該事件折線圖,通過該圖,可以看出我們在不同的時間段,不同事件的執行情況
第十一部分:效能檢測詳情
上面有4個標籤:Summary(效能摘要)
、 Bottom-Up(事件列表,由下至上,對應 Main 火焰圖)
、 Call Tree(每個事件的子項資訊)
、 Event log(事件日誌)
接下來,我們依次詳解
Summary(效能摘要)
其實我們一看就明白,它是一個用來統計在我們檢測效能的時間範圍內,都做了哪些事情:
Loading
:載入時間Scripting
:js計算時間Rendering
:渲染時間Painting
:繪製時間Other
:其他時間Idle
:瀏覽器閒置時間
Bottom-Up(事件列表)
這裡和 Main
裡面看見的,其實是一個對應著的關係,從這裡,我們可以看見所有的事件列表,還有每個事件的 Self Time(自己呼叫的時間)
、 Total Time(總呼叫時間,包括子項呼叫時間)
、 Activity(行為,包括呼叫該事件的位置)
Call Tree(事件子項資訊)
其實這裡和 Bottom-Up
部分是一樣的,就不做太多的說明了,大家看一下就知道了
Event Log(事件日誌)
這裡比前面的 Bottom-Up
和 Call 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()
從瀏覽器的效能資料緩衝區中移除所有 entryType
是 resource
的 performance entries
Performance.getEntries(PerformanceEntryFilterOptions)
PerformanceEntryFilterOptions
引數
可選引數,該引數是一個物件,可接受三個屬性:
name
:performance entry
的名字entryType
:entry
型別. 合法的entry
型別可以從PerformanceEntry.entryType
方法獲取initiatorType
:初始化資源的型別,例如:xmlhttprequest
、other
、script
Performance.getEntries
返回值
Performance.getEntries(PerformanceEntryFilterOptions)
返回值陣列成員按 PerformanceEntry.startTime
時間順序排列
如果沒有符合 filter
條件的物件,那麼返回空陣列. 如果不帶任何引數,返回全部 entries
由於返回值是一個陣列,所以我們接下來講解一下每一個陣列項的每一個屬性的意思:
connectEnd
:連線結束時間connectStart
:連線開始時間decodedBodySize
:解碼的主體大小domComplete
:dom
渲染完成時間domContentLoadedEventEnd
:dom
內容載入事件結束時間domContentLoadedEventStart
:dom
內容載入事件開始時間domInteractive
:dom
互動時間domainLookupEnd
:域查詢結束時間domainLookupStart
:域查詢開始時間duration
:事件耗時encodedBodySize
:編碼主體大小entryType
:資源輸入型別fetchStart
:獲取資源開始時間initiatorType
:發起人型別loadEventEnd
:載入事件結束時間loadEventStart
:載入事件開始時間name
:這裡一般就是當前請求的url
的地址nextHopProtocol
:下一個跳轉協議redirectCount
:重定向次數redirectEnd
:重定向開始時間,如果沒有重定向,值為0redirectStart
:重定向結束時間,如果沒有重定向,值為0requestStart
:請求開始時間responseEnd
:響應結束時間responseStart
:響應開始時間secureConnectionStart
:安全連線開始時間serverTiming
:伺服器時間startTime
:開始時間transferSize
:傳遞大小type
:該事件的型別unloadEventEnd
:解除安裝事件結束時間unloadEventStart
:解除安裝事件開始時間workerStart
:worker
開始時間
Performance.mark(name)
根據給出 name
值,在瀏覽器的效能輸入緩衝區中建立一個相關的時間戳
Performance.measure(name, startMark, endMark)
這裡接收三個引數:
name
:測量的名字startMark
:測量的開始標誌名字(也可以是PerformanceTiming
屬性的名稱)endMark
:測量的結束標誌名字(也可以是PerformanceTiming
屬性的名稱)
Performance.getEntriesByName(name, type)
這裡接收兩個引數:
name
:測量的名字type
:測量的型別(frame, navigation
、resource
、mark
、measure
、paint
)
Performance.getEntriesByType(type)
接收一個引數,type
同上面 Performance.getEntriesByName(name, type)
的 type
Performance.now()
返回一個表示從效能測量時刻開始經過的毫秒數
Performance.setResourceTimingBufferSize(maxSize)
設定瀏覽器應在其效能條目緩衝區中儲存的最大效能條目物件數
Performance.toJSON()
返回 Performance
物件的 JSON
物件
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 審計報表檔案每一個欄位)
大家如果有什麼想法,還請留言,感謝大家支援