Introduction to the

In the previous chapter, we learned that the Web Performance Timing Api can be used to analyze the loading of resources and the Performance (time) of manual delays in Web applications. Now we will look at using Resource Timing to analyze the loading of static resources.

Case study:

In peacetime development, we often encounter such problem feedback;

Customer feedback: friend, how do I feel that our application is so slow in initialization? What is it that makes it go up and down?

Development: I use my phone | computer) tested no problem soon, and I also use Google debugging tools to see the rendering time is really fast.

At this point, for our development, the way we can think of is:

  • Check whether script loading is blocked
  • Check if any resources are loading too slowly (local, own network)
  • For users said slowly, in fact, we, too, don’t know what is says slowly, and then a wave of search on the net, optimization of a wave, what solution did not solve the problem is not test their own, do not know to have people like me feeling is: the development of equipment operation is no problem, started to go wrong) to other devices.

Actually encountered the problem of the most fundamental reason is that we can’t use the data to prove that * * * * what went slowly, what is slow, and we cannot predict in advance to these problems, always can’t let customer his equipment (mobile phone | computer) mailed to you, then you get all kinds of debugging.

In fact, the above case involves many questions:

  • The actual network condition of the user is unknown
  • Don’t know how our code works on the user’s device.
  • It is not clear whether our interface is slow or our code is slow due to the amount of data being computed.
  • Or in the operation of the said code in because of individual data to do data validation (found empty | type does not match…) Page error (not covered in this chapter)

There may be other factors at play;

For us, we should prioritize controllable, predictable performance impacts;

Local debugging analyzes resource loading problems

Examples of code before analysis:


      
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="Width =device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>demo</title>
  <link href="https://cdn.bootcss.com/animate.css/3.7.2/animate.css" rel="stylesheet">
  <link href="https://cdn.bootcss.com/video.js/7.7.6/alt/video-js-cdn.css" rel="stylesheet">
</head>
<body>
<img src="https://www.baidu.com/img/bd_logo1.png">
<img src="https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1585755631&di=5e0530559a cfe3bc031c33c5c6fe38d6&src=http://a3.att.hudong.com/14/75/01300000164186121366756803686.jpg">
</body>
<script src="https://cdn.bootcss.com/video.js/7.7.6/alt/video.core.js"></script>
</html>
Copy the code

In the above code we can see that we have introduced:

  • animate.css
  • video.js
  • video.css
  • Baidu logo
  • And a desktop wallpaper

We run the page locally first, and then look at the console to see how much time they take respectively. The figure below is a simulation of the page opening speed of the user in 200M fiber network after clearing the local cache

From the above data, we can analyze it on our own computer. The resource that takes the longest time is the file of Video-.js. Although I use CDN, it actually feels a bit too long.

From this picture we can see that there are two JS files that take a long time to use but download quickly.

After a wave of local debugger analysis above, we seem to have found some problems, but don’t forget that this is only the result of debugging on our own device, and with a good network (200M fiber network).

However, we don’t know how the user’s device actually opens the web, so we need to capture this data (as much as possible) and analyze it.

Fetching Resource loading process information using Resource Timing

First we use performance. GetEntriesByType (‘ resource ‘) method to get to the browser works began to call this method when the load data for all of the resources.

We’re typing on the console

performance.getEntriesByType('resource')
Copy the code

Let’s first clear the cache and then run the code again. Let’s take a look at the result of this run.

First, we can see that the same device, the same environment, but there is such a big difference in our time results, even more than 3S loading time, which directly leads to our DOM rendering time is extended to 3S+.

If this situation did not occur when we were debugging ourselves, we would never have found this problem. Although I used a third-party CDN, there were still unstable times.

When we call onLoad, the resource Timing returns an array of all the resources we loaded from the moment we opened the page to the DOM rendering.

Then we randomly click on a resource to see what information is available to us:

How much information can be gleaned from the figure above, so let’s look at what these attributes are mainly used for:

PerformanceResourceTiming

attribute describe
entryType The type of EntryTyperesource
name resources URL
startTime At the time the resource extraction begins
duration Time consumed by the whole process =responseEndstartTime
initiatorType Type of resource request initiated
nextHopProtocol Gets the network protocol string for the resource
workerStart Is called if the Service Worker thread is already runningFetchEventReturn immediately beforeDOMHighResTimeStamp, immediately before starting the Service Worker thread if it is not already runningDOMHighResTimeStamp. This property always returns 0 if the resource is not intercepted by the Service Worker
redirectStart The time the initial redirection starts to fetch
redirectEnd Immediately after the last byte of the last redirect response is received
fetchStart Pull resource start time, immediately before the browser starts fetching resources
domainLookupStart Immediately before the browser starts the domain name lookup for the resource
domainLookupEnd Indicates the time after the browser completes the search for the resource’s domain name
connectStart Start TCP connection: Immediately before the browser retrieves the resource and begins establishing a connection to the server
connectEnd End TCP connection: Immediately after the browser has finished connecting to the server to retrieve resources
secureConnectStart Start SSL connection: Immediately before the browser starts the handshake process to protect the current connection
requestStart Right before the browser starts requesting resources from the server
responseStart Immediately after the browser receives the first byte of the response from the server
responseEnd Immediately after the browser receives the last byte of the resource or immediately before the transfer connection is closed, whichever comes first
secureConnectionStart SSL/Initial connection time
transferSize Represents the size, in octets, of the resource to obtaindigital. Includes the size of the response header field and the payload body of the response.
encodedBodySize The size, in octets, received from the extract (HTTP or cache) of the payload body before removing the content encoding of any applicationnumber
decodedBodySize The size, in octets, received from the extract (HTTP or cache) of the message body after removing the content encoding of any applicationnumber
serverTiming Contains timing metrics for the serverPerformanceServerTimingAn array of entries that the server can use to pass data to the front end
PerformanceResourceTiming.initiatorType

The available types are as follows:

type describe
css cssThe resource type
img Image request type
scrpit scrpitScript request type
xmlhttprequest Interface request type
link linkRequest type

The table above lists all the attributes of the resource type and their meanings:

We usually directly forward this data structure to the background for analysis

Note: all times above are relative times, all are relative to the stack time when the program started, not the system timestamp

Then we have the above data for simple analysis, and the results are as follows:

We the this resource file named https://cdn.bootcss.com/video.js/7.7.6/alt/video-js-cdn.css, The time between the creation of the resource initiatorType and the end of DNS resolution for domainLookupEnd is smooth.

SecureConnectionStart (SSL connection), secureConnectionStart (SSL connection), secureConnectionStart (SSL connection), secureConnectionStart (SSL connection), secureConnectionStart (SSL connection)

So here we actually found that we may not be able to repeat the problem during development (this time we were lucky to see the debugger during development), if the user is using it, for us we are ignorant, and do not record the data, So the reason why sometimes the customer speaks slowly but we can not reproduce it (of course, there may be network quality problems, I will talk about how to obtain the user’s current network quality later).

Analyze the data

Here, we can directly use JS to analyze the data we captured:

The code is modified as follows

<! doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, User - scalable = no, initial - scale = 1.0, the maximum - scale = 1.0, Minimum -scale=1.0"> <meta http-equiv=" x-UA-compatible "content=" IE =edge"> <title>demo</title> <link Href = "https://cdn.bootcss.com/animate.css/3.7.2/animate.css" rel = "stylesheet" > < link Href = "https://cdn.bootcss.com/video.js/7.7.6/alt/video-js-cdn.css" rel = "stylesheet" > < style > img {width: 50 px; } .analysisResult { margin-top: 50px; } table { margin-top: 8px; } td { min-width: 70px; padding: 0 6px; } .status { } .status-item { } .color { display: inline-block; height: 10px; width: 10px; } .success { color: green; } .success_back { background: green; } .warning { color: #E6A23C; } .warning_back { background: #E6A23C; } .error { color: red; } .error_back { background: red; } </style> </head> <body> <img src="https://www.baidu.com/img/bd_logo1.png"> <img src="https://ss0.bdstatic.com/94oJfD_bAAcT8t7mm9GUKT-xh_/timg?image&quality=100&size=b4000_4000&sec=1585755631&di=5e0530 559acfe3bc031c33c5c6fe38d6&src=http://a3.att.hudong.com/14/75/01300000164186121366756803686.jpg"> <div class="analysisResult"> <div class="status"> <span class="status-item"> <span class="color success_back"></span> <span class="text"><=50ms</span> </span> <span class="status-item"> <span class="color warning_back"></span> <span class="text"><=100ms</span> </span> <span class="status-item"> <span class="color error_back"></span> <span Class = "text" > > 100 ms < / span > < / span > < / div > < table border = "none" > < thead > < tr > < th > file name < / th > < th > tag type < / th > < th > file type < / th > Analytical time < th > < / th > < th > connection time < / th > < th > response time < / th > < th > file size < / th > < th > start < / th > < th > end time < / th > < th > elapsed time < / th > < / tr > < thead > < tbody id="tableBody"> </tbody> </table> </div> </body> <script SRC = "https://cdn.bootcss.com/video.js/7.7.6/alt/video.core.js" > < / script > < script > window. The onload = function () {let resourceLoadTiming = performance.getEntriesByType('resource'); let tableBody = document.querySelectorAll('#tableBody')[0]; console.log(resourceLoadTiming); resourceLoadTiming.map(({startTime, duration, name, transferSize, responseStart, responseEnd, secureConnectionStart, requestStart, domainLookupStart, domainLookupEnd, initiatorType}) => { if (initiatorType === 'css') return; const tr = document.createElement('tr'); let trClass = ''; let fileName = name.replace(/(^.*\/)(.*)(\.. * $) /, '$2 to $3'); let fileType = name.replace(/(^.*)(\.. * $) /, "$2"); if (duration <= 50) { trClass = 'success'; } else if (duration <= 100) { trClass = 'warning'; } else { trClass = 'error'; } tr.setAttribute('class', trClass); tr.innerHTML = ` <td>${fileName}</td> <td>${initiatorType}</td> <td>${fileType}</td> <td>${(domainLookupEnd - domainLookupStart).toFixed(2)}ms</td> <td>${(requestStart - secureConnectionStart).toFixed(2)}ms</td> <td>${(responseEnd  - responseStart).toFixed(2)}ms</td> <td>${(transferSize / 1000).toFixed(2)}kb</td> <td>${startTime.toFixed(2)}ms</td> <td>${responseEnd.toFixed(2)}ms</td> <td>${duration.toFixed(2)}ms</td> `; tableBody.appendChild(tr); }); }; </script> </html>Copy the code

After we clear the cache and run the code once, we will see the result of our analysis on the page:

In the above because we set the threshold to varying degrees, so I can see no resources are loaded in the 50 ms, if it is, of course, the actual analysis, we also need to add a proportion not all data can be returned within 50 ms, for example, we this time is 10 MB files downloaded a reasonable threshold wouldn’t be 50 ms.

Let’s see if the data we see on the console is consistent with the data we analyze with JS:

In the figure above, we can see that the time we spend on the console is exactly the same as the time we analyze.

In fact, if we want to confirm the accuracy of the data, we need to cache the data we reload after clearing the cache every time, and then do an average processing, such as performing 100 times to see the average data, the more data the closer to the real situation.

If you want to see the actual operation ** please rub here **

conclusion

Through the above operation, we found that Resource loading can be analyzed by Resource Timing. Therefore, a stable and high-performance application needs to do data collection and analysis, as well as the prediction function, so as to ensure that some problems can be predicted in advance. Convenient for our developers to maintain and tune.

Through the data obtained above, we can analyze the following data:

  • DNS resolution time of resource request
  • Time consumed by TCP connections
  • Time spent on SSL connections
  • Request time (server processing time)
  • Response time (download time)
  • The size of the transferred file
  • File size before encoding
  • Decoded file size

The future planning

As for resource analysis, I also developed a small plug-in WebResourceTiming to analyze resource loading in my spare time

V1.0 is expected to be released next week with the following features:

  • You can quickly get the formatted data (all The Times described above are calculated for you)
  • Support the subscriber/publisher mode, support real-time monitoring to obtain the latest resource data
  • There will also be a basisWebResourceTimingModule development resource analysis report widgetWebResourceTimingReportIt will be published to NPM without any third party dependencies.
    • WebResourceTimingReportYou can configure thresholds and hook functions, and customize results. If you do not set thresholds, you can use the default Settings to analyze and generate reports
    • It can only obtain the data of the rendering report without generating the report, which is convenient for the front-end to transmit the data back to the background for data collection

In the future, we will also release the usage of the remaining categories of API, application scenarios and related data analysis plug-ins, and related plug-in usage documents

  • WebRrameTimingHow the pointsAnalyze frame rendering performance informationAnd the supplementarywidgets
  • WebNavigationTimingHow to analyzeNavigational process informationAnd the supplementarywidgets
  • WebMarkTimingHow to use manual dot analysis of ourCode performance and tracking user behavior dataAnd the supplementarywidgets
  • WebPerformanceAnalysisHow to complete the performance analysis of the entire Web page with the above small plug-in, and the performance report generation and related optimization recommendations, loadComponent library

3 April 2020

JBoss