性能优化:Performance API
高标准精度时间(High Resolution Time)规范定义了Performance
接口,支持应用程序(applications)内的客户端延迟测量。
Date 对象表示自1970-01-01起的毫秒精度时间。在实践中,会受制于时钟偏移(clock skew)和系统时钟调整(adjustment of the system clock),所以时间值可能不能保证一直是在增加的,例如:
var mark_start = Date.now(); doTask(); // Some task var duration = Date.now() - mark_start;
duration 可能 >0,<0,=0。
对一些需要计算网页加载时间、脚本执行时间、动画时间或是需要更高精确度等情况就不太够了。
为了保证单调增长(monotonically increasing)且更高精确度的时间值,Performace 接口定义了 DOMHighResTimeStamp
类型,performance.now
方法,performance.timeOrigin
属性。
DOMHighResTimeStamp
单位是毫秒,精确到5微秒(0.005 ms),如果因为硬件或软件的限制, User Agent 不能精确到微秒,则会显示精确到1ms。
typedef double DOMHighResTimeStamp;
Time Origin
计算时间的起始点,
The time origin is the time value from which time is measured:
If the global object is a
Window
object, the time origin MUST be equal to:
- the time when the browsing context(浏览上下文) is first created if there is no previous document;(注:在一个 Web 浏览器内,一个标签页或窗口常包含一个浏览上下文,如一个 iframe 或一个 frameset 内的若干 frame。)
- otherwise, the time of the user confirming the navigation during the previous document's prompt to unload algorithm, if a previous document exists and if the confirmation dialog was displayed;
- otherwise, the time of starting the navigation responsible for loading the Window object's newest Document object.
- If the global object is a
WorkerGlobalScope
object, the time origin MUST be equal to the official moment of creation of the worker.- Otherwise, the time origin is undefined.
在 Chrome DevTools 控制台打印 Performance
:
{ navigation: {type: 0, redirectCount: 0} timeOrigin: 1555386564177.783 timing: { connectEnd: 1555386564181 connectStart: 1555386564181 domComplete: 1555386564345 domContentLoadedEventEnd: 1555386564322 domContentLoadedEventStart: 1555386564318 domInteractive: 1555386564317 domLoading: 1555386564286 domainLookupEnd: 1555386564181 domainLookupStart: 1555386564181 fetchStart: 1555386564181 loadEventEnd: 1555386564345 loadEventStart: 1555386564345 navigationStart: 1555386564177 redirectEnd: 0 redirectStart: 0 requestStart: 1555386564181 responseEnd: 1555386564291 responseStart: 1555386564181 secureConnectionStart: 0 unloadEventEnd: 0 unloadEventStart: 0 } }
Performance 接口
[Exposed=(Window,Worker)] interface Performance : EventTarget { clearMarks: ƒ clearMarks() clearMeasures: ƒ clearMeasures() void clearResourceTimings(); PerformanceEntryList getEntries(); PerformanceEntryList getEntriesByType(DOMString type); PerformanceEntryList getEntriesByName(DOMString name, optional DOMString type); mark: ƒ mark() measure: ƒ measure() memory: (...) readonly attribute PerformanceNavigation navigation; DOMHighResTimeStamp now(); attribute EventHandler onresourcetimingbufferfull; void setResourceTimingBufferSize(unsigned long maxSize); readonly attribute DOMHighResTimeStamp timeOrigin; readonly attribute PerformanceTiming timing; [Default] object toJSON(); };
performance 属性
partial interface WindowOrWorkerGlobalScope { [Replaceable] readonly attribute Performance performance; };
例如 window.performance
,
interface Performance { readonly attribute PerformanceTiming timing; readonly attribute PerformanceNavigation navigation; }; partial interface Window { [Replaceable] readonly attribute Performance performance; };
PerformanceTiming 接口
interface PerformanceTiming { 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; };
- DNS解析:timing.domainLookupEnd - timing.domainLookupStart
- 建立连接:timing.connectEnd - timing.connectStart
- 发送请求:timing.responseStart - timing.requestStart
- 接收请求:timing.responseEnd - timing.responseStart
- 解析DOM树:timing.domInteractive - timing.domLoading
- 页面加载完成:timing.domContentLoadedEventStart - timing.domInteractive
- DOMContentLoaded事件耗时:
timing.domContentLoadedEventEnd - timing.domContentLoadedEventStart
- DOM加载完成:timing.domComplete - timing.domContentLoadedEventEnd
- DOMLoad事件耗时:timing.loadEventEnd - timing.loadEventStart
PerformanceNavigation 接口
interface PerformanceNavigation { const unsigned short TYPE_NAVIGATE = 0; const unsigned short TYPE_RELOAD = 1; const unsigned short TYPE_BACK_FORWARD = 2; const unsigned short TYPE_RESERVED = 255; readonly attribute unsigned short type; readonly attribute unsigned short redirectCount; };
- TYPE_NAVIGATE (0)
通过点击链接、书签、表单提交、脚本、浏览器地址栏输入地址访问
The page was accessed by following a link, a bookmark, a form submission, or a script, or by typing the URL in the address bar. - TYPE_RELOAD (1)
通过点击刷新按钮或是Location.reload()
访问
The page was accessed by clicking the Reload button or via the Location.reload() method. - TYPE_BACK_FORWARD (2)
通过页面前进后退访问
The page was accessed by navigating into the history. - TYPE_RESERVED (255)
其他方式
Any other way.
PerformanceEntry 接口
PerformanceEntry 对象封装了作为性能时间线(performance timeline)一部分的单个性能指标。
[Exposed=(Window,Worker)] interface PerformanceEntry { readonly attribute DOMString name; readonly attribute DOMString entryType; readonly attribute DOMHighResTimeStamp startTime; readonly attribute DOMHighResTimeStamp duration; [Default] object toJSON(); };
partial interface Performance { PerformanceEntryList getEntries (); PerformanceEntryList getEntriesByType (DOMString type); PerformanceEntryList getEntriesByName (DOMString name, optional DOMString type); }; typedef sequence<PerformanceEntry> PerformanceEntryList;
- name:PerformanceEntry 对象标识符,不需要唯一(unique)。
- entryType:该 PerformanceEntry 对象表示的接口的类型。
- startTime:该性能度量的第一个记录时间戳的时间值。
- duration:记录时间,即记录开始到结束的时间。
PerformanceEntry 实例会是下列接口实例之一:
- PerformanceMark
- PerformanceMeasure
- PerformanceFrameTiming
- PerformanceNavigationTiming
- PerformanceResourceTiming
- PerformancePaintTiming
例如在 Chrome DevTools 的控制台打印 performance.getEntries()
,
PerformanceNavigationTiming
[Exposed=Window] interface PerformanceNavigationTiming : PerformanceResourceTiming { readonly attribute DOMHighResTimeStamp unloadEventStart; readonly attribute DOMHighResTimeStamp unloadEventEnd; readonly attribute DOMHighResTimeStamp domInteractive; readonly attribute DOMHighResTimeStamp domContentLoadedEventStart; readonly attribute DOMHighResTimeStamp domContentLoadedEventEnd; readonly attribute DOMHighResTimeStamp domComplete; readonly attribute DOMHighResTimeStamp loadEventStart; readonly attribute DOMHighResTimeStamp loadEventEnd; readonly attribute NavigationType type; readonly attribute unsigned short redirectCount; [Default] object toJSON(); };
{ connectEnd: 3.8349999995261896 connectStart: 3.8349999995261896 decodedBodySize: 74229 domComplete: 336.69000000008964 domContentLoadedEventEnd: 130.1899999998568 domContentLoadedEventStart: 129.47499999791034 domInteractive: 129.42000000111875 domainLookupEnd: 3.8349999995261896 domainLookupStart: 3.8349999995261896 duration: 339.76500000062515 encodedBodySize: 18430 entryType: "navigation" fetchStart: 3.8349999995261896 initiatorType: "navigation" loadEventEnd: 339.76500000062515 loadEventStart: 336.72999999907915 name: "https://developer.mozilla.org/en-US/docs/Web/API/Performance_API" nextHopProtocol: "h2" redirectCount: 0 redirectEnd: 0 redirectStart: 0 requestStart: 5.089999998745043 responseEnd: 15.745000000606524 responseStart: 5.395000000135042 secureConnectionStart: 0 serverTiming: [] startTime: 0 transferSize: 0 type: "back_forward" unloadEventEnd: 16.714999997930136 unloadEventStart: 16.709999999875436 workerStart: 0 }
PerformanceResourceTiming
检索和分析网络加载应用资源(例如 link/script/iframe标签、css中url()
等)的详细网络计时数据。
[Exposed=(Window)] interface PerformanceResourceTiming : PerformanceEntry { readonly attribute DOMString initiatorType; readonly attribute DOMHighResTimeStamp redirectStart; readonly attribute DOMHighResTimeStamp redirectEnd; readonly attribute DOMHighResTimeStamp fetchStart; readonly attribute DOMHighResTimeStamp domainLookupStart; readonly attribute DOMHighResTimeStamp domainLookupEnd; readonly attribute DOMHighResTimeStamp connectStart; readonly attribute DOMHighResTimeStamp connectEnd; readonly attribute DOMHighResTimeStamp secureConnectionStart; readonly attribute DOMHighResTimeStamp requestStart; readonly attribute DOMHighResTimeStamp responseStart; readonly attribute DOMHighResTimeStamp responseEnd; serializer = {inherit, attribute}; };
{ connectEnd: 403.1199999990349 connectStart: 403.1199999990349 decodedBodySize: 33808 domainLookupEnd: 403.1199999990349 domainLookupStart: 403.1199999990349 duration: 1.6250000007858034 encodedBodySize: 33808 entryType: "resource" fetchStart: 403.1199999990349 initiatorType: "link" name: "https://developer.mozilla.org/static/fonts/locales/ZillaSlab-Regular.subset.bbc33fb47cf6.woff2" nextHopProtocol: "h2" redirectEnd: 0 redirectStart: 0 requestStart: 404.0950000016892 responseEnd: 404.7449999998207 responseStart: 404.3100000017148 secureConnectionStart: 0 serverTiming: [] startTime: 403.1199999990349 transferSize: 0 workerStart: 0 }
PerformancePaintTiming
网页构建期间有关“绘制(paint)”(也称为“渲染(render)”)操作的计时信息。 “绘制(paint)”是指将渲染树转换为屏幕上的像素。
interface PerformancePaintTiming : PerformanceEntry {};
{ duration: 0 entryType: "paint" name: "first-paint" startTime: 667.9050000020652 }
参考资料: