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

从历史上看,咱们对客户端性能监控形式十分无限,而且还遇到了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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理