高标准精度时间(High Resolution Time)规范定义了Performance接口,支持应用程序(applications)内的客户端延迟测量。

Date 对象表示自1970-01-01起的毫秒精度时间。在实践中,会受制于时钟偏移(clock skew)和系统时钟调整(adjustment of the system clock),所以时间值可能不能保证一直是在增加的,例如:

var mark_start = Date.now();doTask(); // Some taskvar 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}

参考资料:

  1. High Resolution Time Level 2
  2. MDN - Performance API
  3. Navigation Timing
  4. Performance Timeline Level 2