关于javascript:如何使用Performance-API-来衡量应用性能

4次阅读

共计 5150 个字符,预计需要花费 13 分钟才能阅读完成。

从历史上看,咱们对客户端性能监控形式十分无限,而且还遇到了 API 浏览器的限度,妨碍了咱们精确地掂量客户端性能。

侥幸的是,因为有了新的面向性能的 api,这种状况正在开始扭转。当初,浏览器的 Performance API 给咱们提供了精确度量 Web 页面性能的工具。

不耐烦看的同学能够间接调到开端 应用办法一览

应用 Performance API 的益处

  • 这些 api 减少了在开发工具中使用性能剖析时的教训;
  • Chrome 开发工具和其余工具,如 Lighthouse 只在开发阶段有帮忙。然而应用 Performance API,咱们能够在生产中取得实在的用户度量数据(RUM – real user measurement);
  • 咱们能够失去十分准确的工夫戳数据,这使得这些性能指标的剖析十分精确。

Performance 接口能够获取到以后页面中与性能相干的信息。它是 High Resolution Time API 的一部分,同时也交融了 Performance Timeline API、Navigation Timing API、User Timing API 和 Resource Timing API。
—— MDN

High resolution time

高分辨率工夫的准确水平可达几分之一毫秒。相比之下,基于 Date 的工夫只能准确到毫秒。这种精确度使它成为精确测量工夫的现实工具。

由 User-Agent (UA)测量的高分辨率工夫不会随着零碎工夫的任何更改而更改,因为它是从 UA 创立的全局时钟中获取的。

在 Performance API 中测量的每个测量值都是高分辨率工夫。这就是为什么你总是听到性能 API 是高分辨率工夫 API 的一部分。

Performance timeline API

Performance timeline API 是 Performance API 的扩大。该扩大提供了基于特定筛选条件检索性能指标的接口。

Performance Timeline API 提供了以下三个办法,蕴含在性能接口中:

  • getEntries()
  • getEntriesByName()
  • getEntriesByType()

每个办法返回从 Performance API 的所有其余扩大收集的 entries 列表。

PerformanceObserver 是 API 中蕴含的另一个接口。它次要用于察看性能时间轴(Performance Timeline),并在浏览器记录时告诉新的性能条目。它能够用来度量浏览器和 Node.js 应用程序中某些性能指标。

Performance entries

咱们用 Performance API 度量的货色称为entries。以下是可供咱们应用的性能项:

  • mark
  • measure
  • navigation
  • resource
  • paint
  • frame

应用这些条目和各自的 API 来度量性能。

应用 Navigation timing API 和 Resource timing API 测量

navigation timing API 和 resource timing API 有许多内容重叠,你能够浏览此文章具体理解他们之间的差别。

获取办法:

// Navigation Timing entries:
const navigationEntries = performance.getEntriesByType("navigation")[0];

// 内容
{
  "name": "https://awebsite.com",
  "entryType": "navigation",
  "startTime": 0,
  "duration": 7816.495000151917,
  "initiatorType": "navigation",
  "nextHopProtocol": "","workerStart": 9.504999965429306,"redirectStart": 0,"redirectEnd": 0,"fetchStart": 39.72000000067055,"domainLookupStart": 39.72000000067055,"domainLookupEnd": 39.72000000067055,"connectStart": 39.72000000067055,"connectEnd": 39.72000000067055,"secureConnectionStart": 0,"requestStart": 39.72000000067055,"responseStart": 6608.200000133365,"responseEnd": 6640.834999969229,"transferSize": 0,"encodedBodySize": 0,"decodedBodySize": 0,"serverTiming": [],"unloadEventStart": 0,"unloadEventEnd": 0,"domInteractive": 6812.060000142083,"domContentLoadedEventStart": 6812.115000095218,"domContentLoadedEventEnd": 6813.680000137538,"domComplete": 7727.995000081137,"loadEventStart": 7760.385000146925,"loadEventEnd": 7816.495000151917,"type":"navigate","redirectCount": 0}
// Resource Timing entries
const resourceListEntries = performance.getEntriesByType("resource");

这将返回一个资源计时对象数组。单个对象看起来是这样的,可用于获取某一 Web 资源的前后体现信息:

{
  "name": "https://awebsite.com/images/image.png",
  "entryType": "resource",
  "startTime": 237.85999999381602,
  "duration": 11.274999938905239,
  "initiatorType": "img",
  "nextHopProtocol": "h2",
  "workerStart": 0,
  "redirectStart": 0,
  "redirectEnd": 0,
  "fetchStart": 237.85999999381602,
  "domainLookupStart": 237.85999999381602,
  "domainLookupEnd": 237.85999999381602,
  "connectStart": 237.85999999381602,
  "connectEnd": 237.85999999381602,
  "secureConnectionStart": 0,
  "requestStart": 243.38999995961785,
  "responseStart": 244.40500000491738,
  "responseEnd": 249.13499993272126,
  "transferSize": 0,
  "encodedBodySize": 29009,
  "decodedBodySize": 29009,
  "serverTiming": []}

应用场景一览

// DNS 解析
const dnsTime = navigationEntries.domainLookupEnd - navigationEntries.domainLookupStart;

// 响应 + 响应工夫
const totalTime = navigationEntries.responseEnd - navigationEntries.requestStart;

// 缓存查找响应工夫
const fetchTime = navigationEntries.responseEnd - navigationEntries.fetchStart;

// 应用 Service worker 响应工夫
let workerTime = 0;
if (navigationEntries.workerStart > 0) {workerTime = navigationEntries.responseEnd - navigationEntries.workerStart;}

// 收到第一个字节
const ttfb = navigationEntries.responseStart - navigationEntries.requestStart;

// 重定向工夫
const redirectTime = navigationEntries.redirectEnd - navigationEntries.redirectStart;

// 测量 HTTP 报头大小
const headerSize = navigationEntries.transferSize - navigationEntries.encodedBodySize;

// 测量资源加载工夫
resourceListEntries.forEach(resource => {if (resource.initiatorType == 'img') {console.info(`Time taken to load ${resource.name}: `, resource.responseEnd - resource.startTime);
  }
});

// 获取单个资源指标
const impResourceTime = performance.getEntriesByName("https://awebsite.com/imp-resource.png");

补充:间接应用 performance.timing 计算

正告: 该属性在 Navigation Timing Level 2 specification 中曾经被废除,请应用 PerformanceNavigationTiming 代替。尽管一些浏览器依然反对它,但兴许只是正筹备移除或出于兼容性而保留。

const timingInfo = window.performance.timing;
// DNS 解析,DNS 查问耗时
timingInfo.domainLookupEnd - timingInfo.domainLookupStart;

// TCP 连贯耗时
timingInfo.connectEnd - timingInfo.connectStart;

// 取得首字节消耗工夫,也叫 TTFB
timingInfo.responseStart - timingInfo.navigationStart;

// domReady 工夫(与 DomContentLoad 事件对应)
timingInfo.domContentLoadedEventStart - timingInfo.navigationStart;

// DOM 资源下载
timingInfo.responseEnd - timingInfo.responseStart;

// 筹备新页面工夫耗时
timingInfo.fetchStart - timingInfo.navigationStart;

// 重定向耗时
timingInfo.redirectEnd - timingInfo.redirectStart;

// Appcache 耗时
timingInfo.domainLookupStart - timingInfo.fetchStart;

// unload 前文档耗时
timingInfo.unloadEventEnd - timingInfo.unloadEventStart;

// request 申请耗时
timingInfo.responseEnd - timingInfo.requestStart;

// 申请结束至 DOM 加载
timingInfo.domInteractive - timingInfo.responseEnd;

// 解释 dom 树耗时
timingInfo.domComplete - timingInfo.domInteractive;

// 从开始至 load 总耗时
timingInfo.loadEventEnd - timingInfo.navigationStart;

// 白屏工夫
timingInfo.responseStart - timingInfo.fetchStart;

// 首屏工夫
timingInfo.domComplete - timingInfo.fetchStart;

参考:

Using the Performance API

How to practically use Performance API to measure performance

Performance.timing

正文完
 0