首先 Performance
是一個標準,用於解決開發者在瀏覽器中獲取性能數據的問題。其次, Performance
是一個瀏覽器全局對象,提供了一組 API 用於編程式地獲取程序在某些節點的性能數據。它包含一組高精度時間定義,以及配套的相關方法。javascript
新的 Performance
標準包含了許多 API,它們各自針對性能監控的某個方面。可是目前 Performance
部分標準處於實驗階段,並未穩定發佈,且已發佈的標準,各瀏覽器支持度差別較大。css
API | 描述 | 狀態 | 兼容性 |
---|---|---|---|
Navigation Timing |
導航計時。用於記錄並檢測用戶的設備,網絡等環境,以及頁面初始資源加載和解析耗時。 | 穩定 | >= IE 9 |
High Resolution Timing |
精確計時。用於精確到微秒級別的計時,實際使用時精度受瀏覽器實現限制,一般精確到毫秒 | 穩定 | >= IE 10 |
Resource Timing |
資源計時。對單個網絡資源的計時,包含頁面從打開到獲取時的全部網絡資源。 | 穩定 | >= IE 10, Safari 不支持 |
Page Visiblity |
頁面可見性。獲取頁面是否可見(例如用戶切換了標籤頁,當前頁面隱藏,此時爲不可見) | 穩定 | >= IE 10 |
Battery Status |
電池狀態。獲取當前設備是否充電,電量等級等。對移動設備來講很是實用。 | 穩定 | IE, Safari不支持, Android WebView >=40 |
User Timing |
用戶計時。手動對某段代碼或函數計時。 | 穩定 | >= IE 10, Firfox 40, safari 11 |
Beacon |
燈塔。用於將分析結果和診斷數據採用非阻塞異步的方式發送到服務器,Beacon 方法保證在頁面關閉前執行。 |
實驗 | IE, Safari, IOS, Android 不支持 |
Frame Timing |
幀計時。獲取與幀相關的性能數據,例如每秒幀數 | 實驗 | 不支持 |
PerformanceTiming
接口是爲了向下兼容而存在的接口。它包含了所有的 Navigation Timing
以及部分 Resource Timing
的數據。PerformanceTiming
對象的兼容性是最好的,經過這個接口能夠獲取到頁面從點擊連接到頁面渲染完畢的各個關鍵時間節點。html
經過 window.performance
來獲取 Performance
對象。java
window.performance
// Performance {
// timeOrigin: 1611749316627.347,
// onresourcetimingbufferfull: null,
// eventCounts: EventCounts,
// timing: PerformanceTiming,
// navigation: PerformanceNavigation,
// ...
// }
複製代碼
PerformanceEntry
接口能夠分類獲取 performance 運行時的實例數據,例如手動建立的 mark
標記產生的性能數據,或者是在異步資源加載時(css,script,ajax,等)被動建立的資源標記web
PerformanceTiming
接口提供了在頁面加載和使用時的各類性能計時信息。經過 window.performance.timing
得到一個實例對象。ajax
PerformanceTiming 接口的全部屬性都是隻讀的,且沒有任何繼承屬性,因爲全部屬性均是某個時間點,所以值類型都是 無符號 long long 類型(double)編程
PerformanceTiming.navigationStart
表示同一個瀏覽器上下文中,上一個文檔卸載結束的 UNIX 時間戳。若是沒有上一個文檔,這個值與 PerformanceTiming.fetchStart
相同。數組
PerformanceTiming.unloadEventStart
表示 unload
事件拋出時的 UNIX 時間戳。若是沒有上一個文檔,或者重定向中的一個與當前文檔不一樣源,該值爲 0
。瀏覽器
PerformanceTiming.unloadEventEnd
表示 unload
事件處理完成時的 UNIX 時間戳。若是沒有上一個文檔,或者重定向中的一個與當前文檔不一樣源,該值爲 0
。緩存
PerformanceTiming.redirectStart
表示第一個 HTTP 重定向開始時的 UNIX 時間戳。若是沒有重定向,或者重定向中的一個不一樣源,該值爲 0
。
PerformanceTiming.redirectEnd
表示最後一個 HTTP 重定向完成時(即最後一個 HTTP 響應的最後一個比特被接收到的時間)的 UNIT 時間戳。若是額米有重定向,或者重定向中的一個不一樣源,該值爲 0
。
PerformanceTiming.fetchStart
表示瀏覽器準備好用 HTTP 請求來獲取文檔的 UNIX 時間戳。這個時間早於檢查應用緩存。
PerformanceTiming.domainLookupStart
表示域名查詢開始的 UNIX 時間戳。若是使用了持續鏈接,或者這個信息被存儲到了緩存或本地資源,那麼該值與 PerformanceTiming.fetchStart
相同。
PerformanceTiming.domainLookupEnd
表示域名查詢結束的 UNIX 時間戳。若是使用了持續鏈接,或者這個信息被存儲到了緩存或本地資源,那麼該值與 PerformanceTiming.fetchStart
相同。
PerformanceTiming.connectStart
表示 HTTP 請求開始向服務器發送時的 UNIX 時間戳。若是使用持久鏈接,則該值與 PerformanceTiming.fetchStart
相同。
PerformanceTiming.connectEnd
表示瀏覽器與服務器之間的鏈接創建(即握手與認證等過程所有結束)的 UNIX 時間戳。若是使用持久鏈接,則該值與 PerformanceTiming.fetchStart
相同。
PerformanceTiming.secureConnectionStart
表示瀏覽器與服務器開始安全連接的握手時的 UNIX 時間戳。若是當前網頁不要求安全連接,該值爲 0
。
PerformanceTiming.requestStart
表示瀏覽器向服務器發送 HTTP 請求時的 UNIX 時間戳。
PerformanceTiming.responseStart
表示瀏覽器從服務器收到(或從本地緩存讀取)第一個字節時的 UNIX 時間戳。若是傳輸層從開始請求後失敗並鏈接被重開,該值會被重置爲新的請求的相應的時間。
PerformanceTiming.responseEnd
表示瀏覽器從服務器收到(或從本地緩存讀取,或從本地資源讀取)最後一個字節時(若是在此以前HTTP鏈接已經關閉,則返回關閉的時間)的 UNIX 時間戳。
Performance.domLoading
表示當前網頁 DOM
結構開始解析時(即 Document.readyState
屬性變爲 loading
,相應的 readystatechange
事件觸發時)的 UNIX 時間戳。
Performance.domInteractive
表示當前網頁 DOM
結構解析結束,開始加載內嵌資源時(即 Document.readyState
的屬性爲 interactive
,相應的 readystatechange
事件觸發時)的 UNIX 時間戳。
PerformanceTiming.domContentLoadedEventStart
表示解析器觸發 DomContentLoaded
事件,即全部須要被執行的腳本已經被解析時的 UNIX 時間戳。
PerformanceTiming.domContentLoadedEventEnd
表示全部須要被執行的腳本均已被執行完成時的 UNIX 時間戳。
PerformanceTiming.domComplete
表示文檔解析完成,即 Document.readyState 變爲 complete
且相應的 readystatechange
事件被觸發時的 UNIX 時間戳。
PerformanceTiming.loadEventStart
表示該文檔下,load
事件被觸發的 UNIX 時間戳。若是還未發送,值爲 0
。
PerformanceTiming.loadEventEnd
表示該文檔下,load
事件結束,即加載事件完成時的 UNIX 時間戳,若是事件未觸發或未完成,值爲 0
。
先看一張社區流傳甚廣的圖片:
這張圖描述了從用戶開始路由到這個頁面,到這個頁面徹底加載完成,總過經歷的全部過程,根據圖片,咱們能夠劃分出各個有意義的考察性能的時間節點:
時間段 | 描述 |
---|---|
navigationStart ~ unloadEventEnd |
上一頁面的卸載耗時 |
fetchStart ~ domainLookupStart |
查詢 app DNS 緩存耗時 |
domainLookupStart ~ domainLookupEnd |
dns 查詢耗時 |
connectStart ~ connectEnd |
TCP 鏈接耗時 |
connectEnd ~ secureConnectionStart |
針對 https 協議,在 tcp 握手後,傳輸真正的內容前,創建安全鏈接的耗時 |
fetchStart ~ responseStart |
TTFB (time to first byte), 即首包時長(從用戶代理髮出第一個請求開始,到頁面讀取到第一個字節的耗時)。在一個 web 程序中,用戶代理髮送的第一個 get 請求通常是 index.html,即接收到這個 html 文件的第一個字節的耗費時間 |
responseStart ~ responseEnd |
內容響應時長 |
domLoading ~ domInteractive |
dom 解析完成,即 DOM 樹構建完成的時長 |
domContentLoadedEventEnd ~ loadEventStart |
渲染時長,domContentLoaded 表示 DOM ,CSSOM 均準備就緒(CSSOM 就緒意味着沒有樣式表阻止 js 腳本執行),開始構建渲染樹 |
navigationStart ~ domLoading |
FPT (first paint time), 即首次渲染時間,或白屏時間,從用戶打開頁面開始,到第一次渲染出可見元素爲止 |
navigationStart ~ domInteractive |
TTI (time to interact),首次可交互時間 |
fetchStart ~ domContentLoadedEventEnd |
html 加載完成時間,此時 DOM 已經解析完成 |
navigationStart ~ loadEventStart |
頁面徹底加載完成的時間 |
PerformanceTiming
是向下兼容的舊接口,且只能保存頁面打開過程(從路由到該地址,到當前頁面load事件觸發完成)中的性能數據,若是須要在頁面運行過程當中持續獲取性能數據,須要使用 PerformanceEntry
實例。
Performance.getEntries([filterOption])
方法用於獲取 PerformanceEntry
實例數組,它接受一個可選的參數,若是不傳則獲取所有的 entry
數據。該參數對象能夠包含如下,屬性:
name
: performance entry 的名字entryType
: entry 類型,合法的 entry 值能夠從 PerformanceEntry.entryTypeinitiatorType
: 初始化資源的類型,取值由 PerformanceResourceTiming.initiatorType
接口定義該方法返回 entries
數組,包含了全部符合篩選條件的 entry
。
window.performance.getEntries({ entryType: 'resource' })
/* 0: PerformanceNavigationTiming {unloadEventStart: 0, unloadEventEnd: 0, domInteractive: 1988.2200000574812, domContentLoadedEventStart: 2038.9849999919534, domContentLoadedEventEnd: 2049.5600000722334, …} 1: PerformanceResourceTiming {initiatorType: "link", nextHopProtocol: "h2", workerStart: 0, redirectStart: 0, redirectEnd: 0, …} ... 13: PerformancePaintTiming {name: "first-paint", entryType: "paint", startTime: 1987.154999980703, duration: 0} */
複製代碼
Performance.getEntriesByName(name [, type])
方法接受兩個參數:
name
: 必選,這個 entry 的名稱type
: 可選,想要過濾的 entry 類型返回符合條件的 entries
數組。
window.performance.mark('_my_mark_1')
window.performance.getEntriesByName('_my_mark_1')
// [PerformanceMark]
// 0: PerformanceMark {detail: null, name: "_my_mark_1", entryType: "mark", startTime: 5614367.25000001, duration: 0}
複製代碼
Performance.getEntriesByType(type)
方法接受一個 entryType
,返回符合類型的 PerformanceEntry
列表。
window.performance.getEntriesByType('paint')
/* [PerformancePaintTiming, PerformancePaintTiming] 0: PerformancePaintTiming {name: "first-paint", entryType: "paint", startTime: 2775.984999956563, duration: 0} 1: PerformancePaintTiming {name: "first-contentful-paint", entryType: "paint", startTime: 2775.984999956563, duration: 0} */
複製代碼
PerformanceEntry 的全部屬性都是隻讀的
PerformanceEntry.entryType
是一個 performance entry 的類型,值爲 DOMString
。用於區分不一樣類型的 performance 數據。PerformanceEntry.name
標識當前性能數據塊的名稱,它容許的值和類型隨着 entryType
不一樣而不一樣
值 | 標識的性能時間類型 | name 屬性類型 | name 屬性含義 |
---|---|---|---|
frame , navigation |
PerformanceFrameTiming , PerformanceNavigationTiming |
URL |
產生這兩個performance數據的文檔地址 |
resource |
PerformanceResourceTiming |
URL |
請求的資源的地址,即使請求被重定向了,這個值也不會改變 |
mark |
PerformanceMark |
DOMString |
建立該 mark 時指定的 name 屬性 |
measure |
PerformanceMeasure |
DOMString |
使用 performance.measure() 建立 measure 時提供的 name 屬性 |
paint |
PerformancePaintTiming |
DOMString |
first-paint 或者 first-contentful-paint |
performanceEntry.startTime
表示這個 performance 數據被建立時的時間戳。根據不一樣的 entryType
值,startTime
取值的含義有些不一樣:
frame
: 指定的幀(frame
)開始渲染時的時間mark
: 該 mark
標記被建立時的時間戳(performance.mark()
調用時的時間)measure
: 該 measure 被建立時的時間戳(performance.measure()
方法調用時的時間)navigation
: 值爲 0resource
: 瀏覽器發起該資源請求時的時間戳performanceEntry.duration
表示這個 performance 數據標識的持續時間。根據不一樣的 entryType
值,duration
取值的含義有些不一樣:
frame
: 兩個連續的幀開始渲染的時間之差mark
: 值爲 0,mark
標記沒有持續時間measure
: 要測量的 measure 的持續時間navigation
: performanceEntry.startTime
和 performanceNavigationTiming.loadEventEnd
的差值resource
: 該資源加載的耗時,即 performanceEntry.startTime
和 performanceResourseTiming.responseEnd
的差值Performance
接口除了測量資源加載性能(PerformanceResourceTiming),渲染幀性能(PerformanceFrameTiming),頁面初始化性能(PerformanceNavigationTiming)等等之外,還容許手動建立標記,讓開發者在代碼中測量程序執行的性能。
performance.mark(name)
方法接受一個字符串,用於建立一個標記(mark),字符串即爲這個標記的名稱,這個標記會固定下建立時的時間戳。後續開發者能夠經過不一樣標記的 startTime 值相減來獲取一段代碼的執行耗時,也能夠經過 performance.measure 來計算耗時。該方法返回一個 mark
類型的 PerformanceEntry
實例。
一個標記(mark)具備如下屬性值:
entryType
: 固定爲 mark
name
: 建立標記時經過參數指定的標記名startTime
: 建立 mark
時的時間戳duration
: 0,mark
沒有持續時間window.performance.mark('_test_mark_1')
// PerformanceMark {detail: null, name: "_test_mark_1", entryType: "mark", startTime: 1978026.354999999, duration: 0}
window.performance.mark('_test_mark_2')
// PerformanceMark {detail: null, name: "_test_mark_2", entryType: "mark", startTime: 1991866.0800000008, duration: 0}
window.performance.mark('_test_mark_1')
// PerformanceMark {detail: null, name: "_test_mark_1", entryType: "mark", startTime: 1994302.8449999993, duration: 0}
performance.getEntriesByName('_test_mark_1')
// [PerformanceMark, PerformanceMark]
複製代碼
mark 的 name 不要求惟一
performance.measure(name [, startMarkName [, endMarkName]])
方法建立一個 entryType 類型爲 measure 的 PerformanceEntry 對象,用於計算兩個標誌位之間的間隔時間。它接受三個參數:
name
: 建立 measure 時指定的名稱startMarkName
: 可選,指定做爲開始時間點的 mark 的名稱endMarkName
: 可選,指定做爲結束時間點的 mark 的名稱該方法返回一個 measure
類型的 PerformanceEntry
,它具備如下屬性
entryType
: 值爲 measure
name
: 建立 measure
時的名稱startTime
: 這一段測量的開始時間,若是傳了第二個參數,那就是該 mark 的標記時間duration
: 這一段測量持續的時間window.performance.measure('__measure_test_mark_1', '_test_mark_1')
// PerformanceMeasure {detail: null, name: "__measure_test_mark_1", entryType: "measure", startTime: 1994302.8449999993, duration: 476087.44500000123}
window.performance.measure('__measure_test_mark', '_test_mark_1', '_test_mark_2')
PerformanceMeasure {detail: null, name: "__measure_test_mark", entryType: "measure", startTime: 1994302.8449999993, duration: -2436.7649999985006}
window.performance.measure('__measure_test_mark')
PerformanceMeasure {detail: null, name: "__measure_test_mark", entryType: "measure", startTime: 0, duration: 3290800.8249999993}
複製代碼
綜上, duration
取值有三種狀況
Performance.clearMark([name])
方法用於清理指定的 mark
,若是不提供參數,則全部 entryType 爲 mark
的 PerformanceEntry
所有被清理。Performance.clearMeasure([name])
方法用於清理指定的 measure
,若是不提供參數,則全部 entryType 爲 measure
的 PerformanceEntry
所有被清理。performance.clearMarks('_test_mark_1')
undefined
performance.getEntriesByType('mark')
// [PerformanceMark, PerformanceMark]
// PerformanceMark {detail: null, name: "LUX_end", entryType: "mark", startTime: 2039.1650000001391, duration: 0}
// PerformanceMark {detail: null, name: "_test_mark_2", entryType: "mark", startTime: 1991866.0800000008, duration: 0}
複製代碼