背景

為了提供給前端者監控頁面性能的能力,W3C 定義了一系列相關 API,這裡統稱為 Performance API。目前使用應用廣泛的是 PerformanceTiming,但是除了該 API,新的 W3C 草案及 WICG 提案定義了一系列 PerformanceEntry API。新 API 不僅取代了原 PerformanceTiming 的能力,並增加了更多維度的信息。本文主要針對這些 API 進行介紹。

為了更好地理解目前這些 API 的成熟度,先簡單介紹一下 W3C 標準發布流程

在 W3C 發布一個新標準的過程中,規範是通過下面的嚴格程序由一個簡單的理念逐步確立為推薦標準的:

  • W3C 收到一份提交
  • 由 W3C 發布一份記錄
  • 由 W3C 創建一個工作組
  • 由 W3C 發布一份工作草案
  • 由 W3C 發布一份候選的推薦
  • 由 W3C 發布一份被提議的推薦
  • 由 W3C 發布推薦

文檔演進過程:

W3C 提交 (W3C Submissions) --> W3C 記錄 (W3C Notes) --> W3C 工作組 (W3C Working Groups) --> W3C 工作草案 (W3C Working Drafts) --> W3C 候選推薦 (W3C Candidate Recommendations) --> W3C 提議推薦 (W3C Proposed Recommendations) --> W3C 推薦 (W3C Recommendations)

PerformanceTiming

早期的 Performance 相關信息主要是由 Navigation Timing Recommendations 定義的 PerformanceTiming 提供,包含了載入過程的細分信息:

interfacePerformanceTiming {
readonly attribute unsigned long long navigationStart;
readonly attribute unsigned long long unloadEventStart;
readonly attribute unsigned long long unloadEventEnd;
readonly attribute unsigned long long redirectStart;
readonly attribute unsigned long long redirectEnd;
readonly attribute unsigned long long fetchStart;
readonly attribute unsigned long long domainLookupStart;
readonly attribute unsigned long long domainLookupEnd;
readonly attribute unsigned long long connectStart;
readonly attribute unsigned long long connectEnd;
readonly attribute unsigned long long secureConnectionStart;
readonly attribute unsigned long long requestStart;
readonly attribute unsigned long long responseStart;
readonly attribute unsigned long long responseEnd;
readonly attribute unsigned long long domLoading;
readonly attribute unsigned long long domInteractive;
readonly attribute unsigned long long domContentLoadedEventStart;
readonly attribute unsigned long long domContentLoadedEventEnd;
readonly attribute unsigned long long domComplete;
readonly attribute unsigned long long loadEventStart;
readonly attribute unsigned long long loadEventEnd;};

每個屬性的含義用下面的圖可以直觀地描述:

後面 Chrome 實現了 PerformanceEntry 相關的新 API,提供了更加豐富和詳細的信息。在 Navigation Timing Level 2 草案中,已經廢棄了 PerformanceTiming 介面,並且提供了新的介面 PerformanceNavigationTiming 代替其功能,詳見下面的介紹。

PerformanceEntry

PerformanceEntry 是 W3C Candidate Recommendation 定義的介面,具體的幾種 Entry 類型可以參考 EntryType,但是這裡並沒有列出全部。

3個核心 API 定義如下:

PerformanceEntry:

interfacePerformanceEntry{
readonly attribute DOMString name;
readonly attribute DOMString entryType;
readonly attribute DOMHighResTimeStamp startTime;
readonly attribute DOMHighResTimeStamp duration;
serializer ={attribute};
};

Performance:

partial interfacePerformance{
PerformanceEntryList getEntries();
PerformanceEntryList getEntriesByType(DOMString type);
PerformanceEntryList getEntriesByName(DOMString name,
optional DOMString type);
};

typedef sequence<PerformanceEntry> PerformanceEntryList;

PerformanceObserver:

dictionary PerformanceObserverInit {
required sequence<DOMString> entryTypes;
};
[Exposed=(Window,Worker)] interfacePerformanceObserverEntryList {
PerformanceEntryList getEntries();
PerformanceEntryList getEntriesByType(DOMString type);
PerformanceEntryList getEntriesByName(DOMString name,
optional DOMString type);
};

callback PerformanceObserverCallback = void(PerformanceObserverEntryList entries, PerformanceObserver observer);[Constructor(PerformanceObserverCallback callback),
Exposed=(Window,Worker)] interfacePerformanceObserver {
voidobserve(PerformanceObserverInit options);voiddisconnect();
};

使用示例:

<!doctype html>
<html>
<head>
</head>
<body onload="init()">
<img id="image0"src="https://www.w3.org/Icons/w3c_main.png"/>
<script>
function init() {
performance.mark("startWork"); // see [USER-TIMING]
doWork(); // Some developer code
performance.mark("endWork");
measurePerf();
}
function measurePerf() {
var perfEntries = performance.getEntries();
for (var i = 0; i < perfEntries.length; i++) {
if (window.console) {
console.log("Name: " + perfEntries[i].name +
" Entry Type: " + perfEntries[i].entryType +
" Start Time: " + perfEntries[i].startTime +
" Duration: " + perfEntries[i].duration + "
");
}
}
}
</script>
</body>
</html>

<!doctype html>
<html>
<head>
</head>
<body>
<img id="image0"src="https://www.w3.org/Icons/w3c_main.png"/>
<script>
var doneObservingEvents = false;
var observer = new PerformanceObserver(function(list) {
var perfEntries = list.getEntries();
for (var i = 0; i < perfEntries.length; i++) {
if (window.console) {
console.log("Name: " + perfEntries[i].name +
" Entry Type: " + perfEntries[i].entryType +
" Start Time: " + perfEntries[i].startTime +
" Duration: " + perfEntries[i].duration + "
");
}
}
// maybe disconnect after processing the events.
if (doneObservingEvents) {
observer.disconnect();
}
});
// subscribe to Resource-Timing and User-Timing events
observer.observe({entryTypes: [resource, mark, measure]});
</script>
</body>
</html>

查看 Chromium 源碼,m68 版本現在主要有下面幾種 PerformanceEntry(除了 PerformanceEventTiming 是較新版本增加,其它的 m57 版本均已存在,但是 m57 版本看起來代碼還不成熟):

  • TaskAttributionTiming:配合著 PerformanceLongTaskTiming 來使用,主要是記錄跟 long task 關聯的節點信息;
  • PerformanceLongTaskTiming:用來獲取處理時間較長的任務信息,後面我們會陸續發文介紹,敬請關注;
  • PerformanceEventTiming:用來獲取處理時間較長的 input 事件信息,後面我們會陸續發文介紹,敬請關注;
  • PerformanceResourceTiming:用來監控頁面所以資源的載入時間,後面我們會陸續發文介紹,敬請關注;
  • PerformanceNavigationTiming:用來記錄頁面載入過程的時間信息,它代替了 PerformanceTiming API 的功能,後面我們會陸續發文介紹,敬請關注;
  • PerformancePaintTiming:給前端開發者提供 first paint 和 first contentful paint 信息,後面我們會陸續發文介紹,敬請關注;
  • PerformanceMark & PerformanceMeasure:這2個 Entry 主要是結合 Performance 介面,提供用戶自定義跟蹤 js 腳本性能的方法,後面我們會陸續發文介紹,敬請關注。

對於 WICG draft 提到的 PerformanceFrameTiming,Chrome 目前還沒有相關實現代碼。

最新最好的內核技術文章,請搜索並關注公眾號"U4內核技術"或"u4core"。


推薦閱讀:
相关文章