Front-end monitoring performance indicators

Front-end monitoring performance indicators

Original link

Performance

timestamp-diagram

Stage indicators

field describe Calculation Remark
unload Time-consuming to unload the previous page unloadEventEnd - unloadEventStart When the previous page was unloaded, it may have listened to unload to do some data collection, which will affect the page jump
redirect Time consuming to redirect redirectEnd - redirectStart Excessive redirection affects performance
appCache Caching takes time domainLookupStart - fetchStart
dns Time-consuming DNS resolution domainLookupEnd - domainLookupStart
tcp TCP connection time-consuming connectEnd - connectStart
ssl SSL secure connection takes time connectEnd - secureConnectionStart Only works under HTTPS
ttfb Time to First Byte (TTFB), network request time-consuming responseStart - requestStart
response Time-consuming data transfer responseEnd - responseStart
dom Interactive DOM parsing time-consuming domInteractive - responseEnd Interactive content
dom2 Remaining DOM parsing time-consuming domContentLoadedEventStart - domInteractive DOMContentLoaded All DOM elements are loaded (except async script)
DCL Time-consuming DOMContentLoaded event domContentLoadedEventEnd - domContentLoadedEventStart document.addEventListener(‘DOMContentLoaded’, cb)
resources Time-consuming resource loading loadEventStart - domContentLoadedEventEnd Time from complete DOM (DOMContentLoaded) to resource loading (window.onLoad)
onLoad time-consuming onLoad event loadEventEnd - loadEventStart

Key Performance Indicators

field describe Calculation Remark
firstbyte First package time responseStart - domainLookupStart
fpt First Paint Time, first rendering time/white screen time responseEnd - fetchStart The time difference from the start of the request until the browser starts parsing the first batch of HTML document bytes
tti Time to Interact, first interactive time domInteractive - fetchStart The browser completes all HTML parsing and completes DOM construction, at which point the browser starts loading resources
ready HTML loading completion time, that is, DOM Ready time domContentLoadedEventEnd - fetchStart If the page has synchronously executed JS, synchronous JS execution time = ready - tti
load page full load time loadEventStart - fetchStart load = first rendering time + DOM parsing time + synchronous JS execution + resource loading time

Applets

field describe Calculation Remark
fpt First Paint Time, the first rendering time onShow (first page) - onLaunch (app) The time between the applet's onLaunch and the first page's onShow

W3C Level 1

compatibility

navigation-timing1

conventional usage

  • Calculations main page
const t = performance.timing;

const pageloadtime = t.loadEventStart - t.navigationStart,
  dns = t.domainLookupEnd - t.domainLookupStart,
  tcp = t.connectEnd - t.connectStart,
  ttfb = t.responseStart - t.navigationStart;
  • Calculate Page Resources
const r0 = performance.getEntriesByType('resource')[0];

const loadtime = r0.duration,
  dns = r0.domainLookupEnd - r0.domainLookupStart,
  tcp = r0.connectEnd - r0.connectStart,
  ttfb = r0.responseStart - r0.startTime;

Precautions

1. Calculate the HTML document request using Nav Timing

Get home page html data, should be used performance.timinginstead performance.getEntriesByType('resource')[0].

performance.getEntriesByType('resource')Indicates all static resource information referenced in the current HTML document, excluding its own HTML information.

If it does not currently contain any static resources, then performance.getEntriesByType('resource') === []using [0].xxwill report an error.

2. To calculate static resources, use getEntriesByType('resource') instead of getEntries()

getEntries()Contains the following six types

  1. navigation
  2. resource
  3. mark
  4. measure
  5. paint
  6. frame

In older browsers, getEntries()usually only resourcethe type is equivalent to getEntriesByType('resource').
Because navigationis Navigation Timing 2a specification, older browsers do not support it. And markand measureare User Timinguser- defined types.
The last two are implemented by even fewer browsers for now (2020).

All the use of getEntries()to retrieve static resources requires filtering for several other types, getEntriesByType('resource')which is clear.

3. SecureConnectionStart problem

secureConnectionStartUsed to measure the time spent SSL协商in , there are three possible values

  1. undefined, the browser does not support this attribute;
  2. 0, not using HTTPS;
  3. timestamp timestamp, using HTTPS

There is a bug in the very old version of chrome. When the resource is retrieved to reuse the established HTTPS channel, it is secureConnectionStartset to 0. According to the standard, it should be set to timestamp.

Unsupported and unused situations should be avoided when taking values

const r0 = performance.getEntriesByType('resource')[0];
if ( r0.secureConnectionStart ) {
    
    
  const ssl = r0.connectEnd - r0.secureConnectionStart;
}

4. Cross-domain resource setting response header Timing-Allow-Origin

When obtaining page resource time details, there are cross-domain restrictions. By default, the following attributes of cross-origin resources will be set to 0

redirectStart
redirectEnd
domainLookupStart
domainLookupEnd
connectStart
connectEnd
secureConnectionStart
requestStart
responseStart
  • For controllable cross-domain resources such as your own home CDN, Timing-Allow-Originthe response header origins must at least set the domain name of the main page to allow access to resource time.
  • Generally external public resources are set to Timing-Allow-Origin: *.
  • For third-party uncontrollable resources and no Timing-Allow-Originheader , these invalid data should be filtered out.

If not Timing-Allow-Originset

  1. Without filtering, the reported data will be much better than the actual usage of the user;
  2. After filtering, the resources on the cross-domain CDN cannot report data, so the advantages of being on the CDN cannot be analyzed.
// Resource Timing
const r0 = performance.getEntriesByType('resource')[0],
  loadtime = r0.duration;

// 只要选取上述一个属性(除了secureConnectionStart)进行判断即可
if ( r0.requestStart ) {
    
    
  const dns = r0.domainLookupEnd - r0.domainLookupStart,
    tcp = r0.connectEnd - r0.connectStart,
    ttfb = r0.responseStart - r0.startTime;
}

let ssl = 0; // 默认为 0,当然也可以在数据库层面去做
// 使用了 HTTPS 在计算
if ( r0.secureConnectionStart ) {
    
    
  ssl = r0.connectEnd - r0.secureConnectionStart;
}

5. Pay attention to the meaning of attribute value 0

above we know

  1. secureConnectionStart === 0 when not using HTTPS
  2. Timing-Allow-OriginWhen cross-domain and the correct is not set , there are several attribute values ​​of 0
  • DNS resolution timedomainLookupEnd - domainLookupStart === 0
  1. For resources under the same domain name as HTML, the DNS time may be 0, because the browser will cache the IP of the currently resolved domain name;
  2. The browser pre-resolves the DNS and caches it, <link rel="dns-prefetch" href="//cross-domain.com" />.
  • TCP connection establishment timeconnectEnd – connectStart === 0
  1. For example, the browser can establish 6 independent TCP connections with each host at the same time, then the TCP of the first 6 resources is non-zero, and the remaining keep-alivechannel multiplexing TCP time is 0
  • SSL connectEnd – secureConnectionStart === 0
  1. Same as TCP
  2. Not using HTTPS

In short, there are many scenarios for zero, pay attention to the distinction.

  1. not support
  2. Unused
  3. reuse
  4. cache
  5. Not displayed for security reasons

6、304

There is a bug in the very old chrome version, when 200 is Timing-Allow-Originnot set at 304,
many of the above properties cannot be set to timestamp type but 0.

Then here comes the problem

  1. You filtered 304 cases in #4 and only counted 200 cases. It is well known that 304 caching technical details are better than non-caching 200 cases.
    This will lower your average stat performance.
  2. If you don't filter, you will get better performance statistics than 304.

In this case, there is no way to distinguish for the time being. Fortunately, chrome fixed it in version 37.

PS: The iframe and the document environment are isolated from each other, you can get the contentWindow.performance of the iframe to get it.

W3C Level 2

compatibility

PerformanceNavigationTiming

usage

PerformanceNavigationTiming

  • Replace performance.timing(currently high compatibility, still available, may be deprecated in the future).
const pageNav = performance.getEntriesByType('navigation')[0];
  • PerformanceNavigationTiming uses High-Resolution Time, and the time precision can reach several decimal places in milliseconds.
{
    
    
    "name": "https://developer.mozilla.org/zh-CN/docs/Web/Performance",
    "entryType": "navigation",
    "startTime": 0,
    "duration": 13636.144999996759,
    "initiatorType": "navigation",
    "nextHopProtocol": "h2",
    "workerStart": 0,
    "redirectStart": 0,
    "redirectEnd": 0,
    "fetchStart": 8.684999993420206,
    "domainLookupStart": 8.684999993420206,
    "domainLookupEnd": 8.684999993420206,
    "connectStart": 8.684999993420206,
    "connectEnd": 8.684999993420206,
    "secureConnectionStart": 8.684999993420206,
    "requestStart": 15.749999991385266,
    "responseStart": 10650.364999994054,
    "responseEnd": 13565.22999999288,
    "transferSize": 56666,
    "encodedBodySize": 56127,
    "decodedBodySize": 207120,
    "serverTiming": [],
    "workerTiming": [],
    "unloadEventStart": 10659.469999998691,
    "unloadEventEnd": 10659.5299999899,
    "domInteractive": 13574.969999986934,
    "domContentLoadedEventStart": 13612.624999994296,
    "domContentLoadedEventEnd": 13612.629999988712,
    "domComplete": 13635.66999998875,
    "loadEventStart": 13635.704999993322,
    "loadEventEnd": 13636.144999996759,
    "type": "navigate",
    "redirectCount": 0
}
  • A lot of properties have been added to get more detailed information (resource is the same).
// Service worker 响应时间
let workerTime = 0;
if (pageNav.workerStart > 0) {
    
    
  workerTime = pageNav.responseEnd - pageNav.workerStart;
}

// HTTP header 大小
const headerSize = pageNav.transferSize - pageNav.encodedBodySize;

// 压缩比率,如果是 1 的话,也能说明未开启例如 gzip
const compressionRatio = pageNav.decodedBodySize / pageNav.encodedBodySize;
  • Compatible, because if it cannot performance.getEntriesByType('navigation')be fetched , no error will be reported but an empty array will be returned.
if (performance.getEntriesByType('navigation').length > 0) {
    
    
  // We have Navigation Timing API
}

Paint timing

google-rendering

Paint Timing defines two new metrics:

  1. First-paint (FP, first-paint), the point at which the browser renders any content that is visually different from the content on the screen before navigating. Isn't this time-consuming white screen.
  2. The first content painting (FCP, first-contentful-paint), the time point when the browser renders the first content from the DOM. Isn't this time-consuming gray screen?
// 直接在代码里这么用的话,不一定取得到,需要轮询
performance.getEntriesByType('paint');
[
  {
    
    
    "name": "first-paint",
    "entryType": "paint",
    "startTime": 17718.514999956824,
    "duration": 0
  },
  {
    
    
    "name": "first-contentful-paint",
    "entryType": "paint",
    "startTime": 17718.519999994896,
    "duration": 0
  }
]
  • performance.getEntriesByTypeWhat is returned is an array, and only prepared data can be included in the group. You may need to poll or find an appropriate time point to report the data.
    The new standard provides PerformanceObserveran API to help you monitor whether the response resource data is ready.
const observer = new PerformanceObserver((list) => {
    
    
  for (const entry of list.getEntries()) {
    
    
    // `name` will be either 'first-paint' or 'first-contentful-paint'.
    const metricName = entry.name;
    const time = Math.round(entry.startTime + entry.duration);

    collect({
    
    
      name: metricName,
      time: time,
    });
  }
});
observer.observe({
    
    entryTypes: ['paint'/* , 'navigation', resource */]});
  • Use needs to be code compatible
if ('performance' in window) {
    
    
  if ('PerformanceObserver' in window) {
    
    
    // todo
  } else {
    
    
    // todo
  }
}
  • Effectively draw First Meaning Paint (FMP) for the first time: Indicates the time point at which the element that the current page most wants to display to the user is rendered, that is, the main element rendering point.
  • FMP does not have a standardized definition and needs to develop its own definition. For example, the point in time when the element's growth rate is the steepest.

User timing

  • performance.markDot, the parameter is the mark of the point name
performance.mark('starting_calculations');
const multiply = 82 * 21;
performance.mark('ending_calculations');

performance.mark('starting_awesome_script');
function awesomeScript() {
    
    
  console.log('doing awesome stuff');
}
performance.mark('ending_awesome_script');
  • performance.measureCalculation, the parameters are point name identification, mark point 1, mark point 2
performance.mark('starting_calculations');
const multiply = 82 * 21;
performance.mark('ending_calculations');
+ performance.measure('multiply_measure', 'starting_calculations', 'starting_calculations');

performance.mark('starting_awesome_script');
function awesomeScript() {
  console.log('doing awesome stuff');
}
performance.mark('starting_awesome_script');
+ performance.measure('awesome_script', 'starting_awesome_script', 'starting_awesome_script');
  • take out time
const measures = performance.getEntriesByType('measure');
measures.forEach(measureItem => {
    
    
  console.log(`${
      
      measureItem.name}: ${
      
      measureItem.duration}`);
});

Report data

  • Generally, it can be considered to report when the user is about to uninstall the page. There is no doubt that this time point will not interfere with the user's operation on the current page.
    However, if the reporting takes a long time, it will affect the user experience of jumping to the next page. can be used navigator.sendBeacon.
window.addEventListener('unload', function() {
    
    
  // 注意 performance.getEntries 会取当前页所有资源包括页面本身的性能信息
  // 注意 数据体量问题
  let rumData = new FormData();
  rumData.append('entries', JSON.stringify(performance.getEntries()));

  // 是否支持
  if('sendBeacon' in navigator) {
    
    
    // Beacon 发起请求
    if(navigator.sendBeacon(endpoint, rumData)) {
    
    
      // sendBeacon 发送成功
    } else {
    
    
      // sendBeacon 发送失败! 使用 XHR or fetch 代替
    }
  } else {
    
    
    // sendBeacon 不支持! 使用 XHR or fetch 代替
  }
}, false);
  • Traditional solution, handled unloadin
  1. Because the page is unloaded, it will not care about the completion of receiving asynchronous ajax, so synchronous ajax is generally used to block page unloading.
  2. Create an image and send the request with img src.
  3. setTimeout(ajax, 0)。
  • navigator.sendBeacon solves the above problems
  1. After the page is uninstalled, asynchronous requests can still be made.
  2. Does not block unloading of the current page.
  3. Simple to use.

Summarize

  • Navigation TimingCollect HTML document performance metrics.
  1. performance.timingCommonly used to solve compatibility
  2. performance.getEntriesByType('navigation')[0]New standard, high precision, more detailed content, poor compatibility
  • Resource TimingCollect performance indicators of resources that HTML depends on, such as CSS, JS, images, fonts, etc.
  1. performance.getEntriesByType('resource')Use old and new, extended by new standards.
  • User timingCollect user-defined
  1. performance.getEntriesByType('measure')It can be considered to be used to manage FMP.

reference

  1. HTML DOM standard
  2. W3C Navigation Timing
  3. Navigation Timing Level 2
  4. User Timing Level 2
  5. boomerang
  6. commercial boomerang
  7. Resource Timing practical tips
  8. Front-end monitoring practice - FMP's intelligent acquisition algorithm
  9. Assessing Loading Performance in Real Life with Navigation and Resource Timing
  10. Navigator.sendBeacon
  11. performance-bookmarklet
  12. waterfall.js

Guess you like

Origin blog.csdn.net/guduyibeizi/article/details/105263127