In-depth understanding of front-end performance monitoring

  javascript, Performance monitoring

Under the same network environment, there are two websites that can also meet your needs. One website is loaded in a swish, and the other one is displayed only after turning around for half a day. If you were given a choice, which one would you use?

图片描述

The performance of the page is an important link in front-end development, but we have not had a better method to detect the performance of the page. Until the W3C Performance Team introduced the new API window.performance, browsers above IE9 currently support it. It is an object used in a browser to record key points in the process of page loading and parsing. It is placed in a global environment and can be accessed through JavaScript.

Use performance apis

You can detect and compatible performance by the following methods:

var performance = window.performance ||
window.msPerformance ||
window.webkitPerformance;
if (performance) {
//your code
}

Let’s take a look at it first.The structure of performance

图片描述

performance.memoryIs to show the memory usage at this moment, it is a dynamic value, where:
UsedJSHeapSize indicates the amount of memory occupied by JS objects (including objects inside the V8 engine)
TotalJSHeapSize indicates: available memory
JsHeapSizeLimit: Memory Size Limit
Generally, usedJSHeapSize cannot be greater than totalJSHeapSize. if it is greater than, there may be a memory leak.

performance.navigationDisplays the source information for the page, where:
RedirectCount indicates that if there is redirection, the page will jump through several redirects, and the default is 0
Type indicates how the page opens.
0 indicates the page normally entered by TYPE_NAVIGATENEXT (non-refresh, non-redirection, etc.)
1 indicates the page refreshed by TYPE_RELOAD through window.location.reload ()
2 indicates the page (history) entered by TYPE_BACK_FORWARD through the browser’s forward and backward buttons
255 indicates a page entered by TYPE_UNDEFINED other than the above

performance.onresourcetimingbufferfullThe property is an event handler that is called when the resourcetimingbufferfull event is triggered. Its value is a manually set callback function that executes when the browser’s resource time performance buffer is full.

performance.timeOriginIs the reference point for a series of time points, accurate to one over ten thousand milliseconds.

performance.timingIt is a series of key time points, including a series of time data such as network and analysis.

图片描述

The following is an explanation of these time points

timing: {
 //Time stamp at the end of unloading a page on the same browser.  If there is no previous page, this value will be the same as fetchStart.
 navigationStart: 1543806782096,
 
 //timestamp of the last page when the unload event was thrown.  If there is no previous page, this value will return 0.
 unloadEventStart: 1543806782523,
 
 //Corresponds to unloadEventStart, timestamp when unload event processing is completed.  If there is no previous page, this value will return 0.
 unloadEventEnd: 1543806782523,
 
 //Time stamp at the beginning of the first HTTP redirect.  If there is no redirection or a different source in the redirection, this value returns 0.
 redirectStart: 0,
 
 //The timestamp of when the last HTTP redirect was completed (that is, when the last bit of the HTTP response was received directly).
 //If there is no redirection or a different source in redirection, this value will return 0.
 redirectEnd: 0,
 
 //The browser is ready to use HTTP requests to fetch the timestamp of the document.  This point in time will be before checking any application cache.
 fetchStart: 1543806782096,
 
 //UNIX timestamp of DNS domain name query start.
 //If a persistent connection is used or this information is stored in a cache or local resource, this value will be consistent with fetchStart.
 domainLookupStart: 1543806782096,
 
 // DNS domain name query completion time.
 //if local cache (i.e. no DNS query) or persistent connection is used, it is equal to fetchStart value
 domainLookupEnd: 1543806782096,
 
 //Time stamp of the end of HTTP (TCP) domain name query.
 //If a persistent connection is used or this information is stored in a cache or local resource, this value will be consistent with fetchStart.
 connectStart: 1543806782099,
 
 // HTTP(TCP) returns the timestamp when the connection between the browser and the server was established.
 //If a persistent connection is established, the return value is equivalent to the value of the fetchStart property.  Connection establishment refers to the complete end of all handshake and authentication processes.
 connectEnd: 1543806782227,
 
 // HTTPS returns the timestamp when the browser and the server started the handshake of the secure link.  Returns 0 if the current web page does not require a secure connection.
 secureConnectionStart: 1543806782162,
 
 //Returns the timestamp of when the browser made an HTTP request to the server (or when it started reading the local cache).
 requestStart: 1543806782241,
 
 //Returns the timestamp when the browser received (or read from the local cache) the first byte from the server.
 //If the transport layer fails after starting the request and the connection is reopened, this attribute will be counted as the corresponding initiation time for the new request.
 responseStart: 1543806782516,
 
 //Returns when the browser receives the last byte from the server (either from the local cache or from a local resource)
 //(If the HTTP connection has been closed before this, the timestamp of when it was closed is returned).
 responseEnd: 1543806782537,
 
 //Time stamp when the DOM structure of the current webpage starts parsing (that is, when the Document.readyState property changes to "loading" and the corresponding readystatechange event triggers).
 domLoading: 1543806782573,
 
 //Time stamp when the DOM structure of the current webpage finishes parsing and starts loading embedded resources (i.e. when the Document.readyState property becomes "interactive" and the corresponding readystatechange event triggers).
 domInteractive: 1543806783203,
 
 //When the parser sends DOMContentLoaded event, that is, the timestamp when all scripts that need to be executed have been parsed.
 domContentLoadedEventStart: 1543806783203,
 
 //Time stamp when all scripts requiring immediate execution have been executed (regardless of execution order).
 domContentLoadedEventEnd: 1543806783216,
 
 //The current document parsing is completed, that is, the timestamp when the Document.readyState becomes' complete' and the corresponding readystatechange is triggered
 domComplete: 1543806783796,
 
 //Time stamp when the LOAD event was sent.  If this event has not been sent, its value will be 0.
 loadEventStart: 1543806783796,
 
 //Time stamp when the load event ends, that is, when the load event completes.  If this event has not been sent or completed, its value will be 0.
 loadEventEnd: 1543806783802
 }

These parameters are very useful and can help us to obtain the Domready time, onload time, white screen time, etc. of the page, as well as the performance parameters of a single page resource from sending the request to obtaining RS rsponse.

The page performance data that is useful to us probably includes the following parameters. These parameters are composed of the differences of the above performance.timing attributes. It is a value accurate to milliseconds. The calculation method is as follows:

  • Redirect time consuming: redirectEnd-redirectStart
  • DNS query takes time: domainlookupend-domainlookuptart
  • TCP link time consuming: connectEnd-connectStart
  • HTTP request takes time: responseEnd-responseStart
  • Parsing dom tree takes time: domComplete-domInteractive
  • White screen time: responseStart-navigationStart
  • DOMready time: domcontentloadedeventend-navigationstart
  • Onload Time: LoadEventNavigationStart, which is the time when the onload callback function is executed.

How to optimize?

Redirection optimization:There are three types of redirection, 301 (permanent redirect), 302 (temporary redirection) and 304(Not Modified). 304 is used to optimize the cache, which is very useful. The first two should be avoided as much as possible. Any code that needs to redirect the jump code can write the redirected address directly to the html or JS in the front end, which can reduce the communication process between the client and the server and save the redirection time.

DNS optimization:Generally speaking, there are two points related to DNS in front-end optimization: one is to reduce the number of DNS requests, and the other is to perform DNS Prefetching. A typical DNS resolution takes 20-120 milliseconds (the mobile terminal will be slower), reducing the number of DNS resolutions is a good optimization method, and putting all kinds of resources on a cdn domain name as far as possible. DNS Prefetching allows domain names with this attribute to be parsed in the background without the user clicking a link, while domain name parsing and content loading are serial network operations, so this method can reduce the waiting time of users and improve the user experience. The new version of the browser will pre-fetch domain names that are not in the same domain as the current domain name (the domain name browsing the web page) on the page and cache the results, which is the implicit DNS Prefetch. If you want to pre-fetch domains that do not appear on the page, you will need to use the DNS Prefetch shown. The following figure shows the method of DNS Prefetch:

<html>
<head>
< title > Tencent < /title >
<link rel="dns-prefetch" href="//mat1.gtimg.com"  />
<link rel="dns-prefetch" href="//inews.gtimg.com"  />
<link rel="dns-prefetch" href="//wx.qlogo.cn"  />
<link rel="dns-prefetch" href="//coral.qq.com" />
<link rel="dns-prefetch" href="//pingjs.qq.com"  />

TCP request optimization:TCP optimization is mostly on the server side. What the front end can do is to minimize the number of TCP requests, that is, to reduce the number of HTTP requests. Http 1.0 uses short connection by default, which is also a short connection of TCP, that is, the client and the server establish a connection every time they perform http operation, and the connection is interrupted when the task ends. In this process, there are 3 TCP request handshakes and 4 TCP request releases. There are two ways to reduce TCP requests. One is resource merging, which merges pictures, css and js in the page to reduce the amount of requests. The other uses a long link, using http1.1, and adds a Connection:keep-alive to the HTTP response header. When a web page is opened, the connection will not be closed immediately. When accessing this service again, the long link will continue to be used. This greatly reduces the number of handshakes and releases of TCP. Or use Websocket to communicate, only need to establish TCP link once in the whole process.

HTTP request optimization:Use a content delivery network (CDN) and reduce requests. Using CDN can reduce the network request delay. The domain name of CDN should not be the same as the domain name of the master station. This will prevent the problem of carrying cookie of the master station when accessing CDN. For network requests, fetch can be used to send cookie-free requests and reduce the size of http packets. You can also use a local cache policy to minimize duplicate access to server data.

Rendering optimization:In the browser-side rendering process, such as large frames, vue and react, its templates are actually rendered on the browser side, not straight html, but the relevant frame code in the frame is used to render the page. This rendering process has a great loss for the first screen and the time for the white screen will be increased. If necessary, the whole html can be rendered on the server side, so that the whole html can be directly output to our browser side instead of rendering on the browser side.

图片描述

Another problem is that, by default, JavaScript execution will “block the parser.” When the browser encounters a script outer chain tag, DOM construction will be suspended, and control will be transferred to JavaScript execution. After the script is downloaded and executed, DOM construction will continue. And inline scripts always block parsers unless extra code is written to delay their execution. We can add the outer chain of script to the bottom of the page, or we can use defer or async to delay execution. The difference between defer and async is that defer is orderly, and the code is executed in the order of html, while async is unordered, and will be executed as soon as the download is completed. Or use asynchronous programming methods, such as settimeout, or use multiline webworker, which do not hinder DOM rendering.

<script async type="text/javascript" src="app1.js"></script>
 <script defer type="text/javascript" src="app2.js"></script>

Resource performance apis

Performance.timing records the overall performance indicators used to analyze the page. If you want to obtain performance indicators for individual resources (e.g. JS, pictures), you need to use the Resource Timing API.
performance.getEntries()Method, which contains an array list of all static resources; Each item is a request. Relevant parameters include name, type, time, etc. The following figure shows chrome’s list of related resources on Tencent.

图片描述

As you can see, compared with performance.timing: there are no DOM-related attributes, and new ones have been addednameentryTypeinitiatorTypeAnddurationFour attributes. They are

  • Name means: the name of the resource, which is also the absolute path of the resource, can be obtained through performance. getentrybyname (the value of the name attribute) to obtain the specific attribute loaded by this resource.
  • EntryType means: the resource type “resource”, there are 3 other types of “navigation”, “mark” and “measure”.

    图片描述

  • InitiatorType indicates: the request source “link” means < link > label, and “script” means < script >, “img” means < img > label, “css” means the url way of background to load resources, and “redirect” means redirection, etc.

    图片描述

  • Duration: Load time is a millisecond number.

Due to the influence of homologous policies, the time point obtained by cross-domain resources is usually 0. If more detailed and accurate time points are needed, resources can be requested to pass alone.performance.timingGet. Or the resource server opens the response header Timing-Allow-Origin and adds the designated source site as follows:

Timing-Allow-Origin:  https://qq.com

Method set

Except ..performance.getEntriesIn addition,performanceIt also contains a series of useful methods. The following figure

图片描述

performance.now()
performance.now()Returns a timestamp of the execution time of the current page, which is used to accurately calculate the execution time of the program. AndDate.now()The difference is that it uses a floating point number, which returns the time in milliseconds with the decimal point accurate to microsecond level, which is more accurate. And will not be affected by system program execution blocking.performance.now()The time of is increasing at a constant rate and is not affected by system time (system time can be adjusted manually or by software).performance.timing.navigationStart + performance.now()Approximately equalDate.now().

let t0 = window.performance.now();
 doSomething();
 let t1 = window.performance.now();
 Log ("dosomething function executed"+(t1-t0)+"ms.")

Through this method, we can test how long a piece of code has been executed.

performance.mark()
The mark method is used to customize when to add a mark. The usage method is as follows:

var nameStart = 'markStart';
 var nameEnd   = 'markEnd';
 //Mark the function before execution
 window.performance.mark(nameStart);
 for (var i = 0;   i < n;  i++) {
 doSomething
 }
 //Mark the function after execution
 window.performance.mark(nameEnd);
 //Then measure the time distance between the two marks and save it
 var name = 'myMeasure';
 window.performance.measure(name, nameStart, nameEnd);

The saved value can be passed throughperformance.getEntriesByname( ‘myMeasure’ )Or ..performance.getEntriesByType(‘measure’) query.

Performance.clearMeasures()
Removes custom added measure from the browser’s performance input buffer

Performance.getEntriesByName()
Returns a list of PerformanceEntry objects based on the given name and entry type.

Performance.getEntriesByType()
Returns a list of PerformanceEntry objects based on the given entry type

Performance.measure()
Create a timestamp with the specified name in the performance input buffer between the specified start mark and end mark of the browser, as shown in the above example.

Performance.toJSON()
Is a JSON format converter that returns the JSON object of the Performance object

Resource buffer monitoring

Performance.setResourceTimingBufferSize()
Set the maximum number of resource data that can be cached on the current page, and the number of resource data whose entryType is Resource. When exceeded, all resource data with entryType resource will be cleared. The parameter is an integer (maxSize). OnResourceTimingBufferfull event can effectively monitor the resource buffer. This event is triggered when the number of resources with entryType resource exceeds the set value.
Performance.clearResourceTimings()
Remove all performance entries whose entryType is “resource” from the browser’s performance data buffer.
The following is a demo of this attribute on mdn. The main content of this demo is to call the buffer_full function when the buffer is full.

function buffer_full(event) {
console.log("WARNING: Resource Timing Buffer is FULL!"  );
performance.setResourceTimingBufferSize(200);
}
function init() {
// Set a callback if the resource buffer becomes filled
performance.onresourcetimingbufferfull = buffer_full;
}
<body onload="init()">

Using these properties and methods of performance, we can accurately record the time we want, and with the help of log collection and other functions, we can easily master the various performance indicators of our website.

Compatibility

At present, although mainstream browsers already support performance objects, they cannot support all the attributes and methods above it, with some slight differences. This article mainly tests related properties and methods based on chrome and qq browsers, which can be used.

What have we done? (Focus)

At present, many performance monitoring and analysis tools are implemented through data reporting, which cannot timely and effectively feedback the performance problems of the page, and can only be known after users report the problems (after the problems occur). Therefore, the news-based front-end team has made a real-time performance checking tool based on the performance API, which can give detailed reports and solve performance problems in the development phase.

superProfiler[In External Open Source Process]

图片描述

It is a JavaScript performance monitoring tool library, which is loaded and displayed on the right side of the page through script reference. Without relying on any library or script, it can view the FPS, code execution time, memory occupation, network performance and resource occupation of the current page in real time.

 图片描述

You can also view the average of the most recent (10) page performance. Click the “Generate Report” button to generate a more detailed overview of the data report.

图片描述

Summary

The Performance API is very useful for front-end performance monitoring. It provides many interfaces to test our program performance. Mark and measure, for example. Many excellent frameworks have also been tested with this API. Mark and measure are frequently used in it to test program performance. Therefore, in order to develop high-performance web programs, it is very important to understand the Performace API. Finally, the superProfiler tool can find out the performance problems more quickly and conveniently, break down the problems in a targeted way, improve the development efficiency and enhance the user experience. Of course, this is only the first step in front-end performance optimization, and the path resistance is long. I hope everyone can raise questions and point out doubts and make progress together.

Author: TNFE Dapeng elder brother

Team promotion

Finally,Tencent News TNFE Front End TeamFor front-end developers, the latest high-quality content in small programs and web front-end technologies has been compiled. It is updated weekly. Welcome to star, github address:https://github.com/Tnfe/TNFE- …