background

The small program we are responsible for has been in operation since 2017, with dozens of pages, more and more content, and worse and worse performance. For a period of time, there were often delays and fever of user feedback, which greatly affected user experience.

In the early stage, a lot of lag can be obviously perceived, and we have gradually optimized this part of performance problems. The obvious lag has been resolved, the remaining performance issues will only appear on older and low-end phones, and only in special scenarios, requiring comprehensive performance monitoring to find these less obvious performance issues.

In addition, we also need to know whether our optimization strategy is correct and whether the optimization priority is correct. At this time, if we can see the actual effect of each version after optimization, we will have more goals and steps.

Ready-made performance monitoring tools

Wechat small program system itself has several means to do performance monitoring, can help us solve a lot of problems, but there are some defects, first to understand the existing means that can be directly used.

Wechat background – Performance monitoring

In the background of wechat mini program, development management – monitoring alarm – performance monitoring includes the open rate, start-up time, code package downloads, opening time distribution and lost time distribution, among which “start-up time at each stage” is the one we use most.Advantages: You can see the time of important phases of small programs in a macro way.

Disadvantages:

  1. Data exists for only 60 days, so long-term monitoring is not possible.
  2. Cannot be viewed by page, component, etc.
  3. Data often can not brush out, many times can only view 7 days of data;

However, total startup time is a meaningful indicator, and startup speed is directly related to user churn. I have experienced this. Once in offline promotion, an old man had to wait 3~4 minutes to open the small program because of his old mobile phone style and 4G performance. Even if there was a gift registered offline, the user almost gave up. So startup time is also a performance indicator that our team must look at every week.

Experience rating tool

The experience score in the small program developer tool is also a means of performance analysis, which can be monitored in real time during the running process and scored after the completion of the experience. The scoring dimension is divided into: total score, performance, experience and best practice.

It can be used as an aid in the development process, as a means of discovering performance and experience problems.

Disadvantages:

  1. To run manually, and each operation path is different score is also different;
  2. Depending on local data, some online scenarios cannot be covered.

Tencent Performance Dog

PerfDog is another stand-alone performance testing tool, which supports ios and Android systems and can test the performance of real computers. The collected data is more detailed and complete, so it is a good tool.

Disadvantages:

  1. Stand-alone test, not the overall user situation;
  2. The operation is more complicated;
  3. Currently charged;

The existing performance testing tools have a number of shortcomings, either for single machine or dimension is not fine-grained, which is why we developed our own performance monitoring.

Performance monitoring schemes

So how do we monitor performance, and what makes sense to monitor?

The user opens the applet by starting the applet, loading the page, rendering the page, switching the page, performing operations, and exiting the applet.

We chose three directions for performance monitoring, which can monitor the performance data of users at each stage from opening to exiting.

Startup Time Monitoring

Wechat officially provides the Wx.getPerformance () API, which can be used to obtain the time of startup and page switching.

In the startup time, we reported the startup time, page page rendering time, and script injection time

First, you need to create a performance listener

// Monitor performance
if (wx.canIUse('getPerformance')) {
    const performance = wx.getPerformance()
    this.performanceObserver = performance.createObserver((entryList: WechatMiniprogram.EntryList) = > {
        const entryArray = entryList.getEntries()
        entryArray.forEach((element: PerformanceEntryObject) = > {
            const {
                name, duration, path, moduleName, navigationType,
            } = element
            duration && this.report(name, duration, {
                path,
                moduleName,
                navigationType,
            })
        })
    })
    this.performanceObserver.observe({ entryTypes: ['navigation'.'render'.'script']})}Copy the code

Here we only listen for the startup time.

AppLaunch, firstRender, evaluateScript were screened by name attribute, and the startup time, first rendering time, and script injection time were obtained successively.

Wechat also provides the small program speed measurement function, which can report the performance data obtained by wx.getPerformance() to the wechat background via wx.reportPerformance(). However, the data can only be kept for 7 days, and the performance data of multiple versions cannot be compared. So we report it to our own data platform.

Page hop Monitoring

Performance data for page switching back and forth can also be obtained from wx.getPerformance(), which can be filtered from route, evaluateScript, and firstRender to get page routing times, script injection times, and page first rendering times. Methods and startup time are similar, not detailed.

SetData performance monitoring

After entering the page, the biggest impact on performance is the wrong use of setData. There are two main aspects. One is that frequent setData leads to frequent refresh and lag. Therefore, we also monitor the two directions, frequent setData and setData data volume is too large.

Performance monitoring of setData by enclosing setUpdatePerformanceListener () API. It returns a timestamp of the major update step in each update, which can be used to roughly estimate custom component (or page) update performance.

The following fields can be obtained:

The setData of each page and component must be very frequent. If we report them all, the amount of data will be too large. We want to monitor setData with frequent and large data volume, so we can put the computing resources consumed in the end.

We set two indicators:

Jank_times: indicates the number of setData frequencies greater than 10 times within 1 second.

Stutter_times: indicates the number of times that the setData time exceeds 50ms.

All setData are monitored in the small program. Only the data that trigger these two indicators are reported, and the page path, component path, data field information and other contents are retained in the reported data. After abnormal setData is achieved, it can be analyzed and optimized based on these data.

The field name Parameters that The data type note
name mini_set_data string
page Page path string
set_data_info SetData information Object The data uploaded at a time does not exceed 10 MB
set_data_times Total number of setData stays on the page number The page contains the component setData frequency
jank_times The number of setData frequencies greater than 10 in 1 second number Number of times setData frequency is too high per unit of time (configurable)
stutter_times Number of times that setData takes more than 50ms in a single operation number

The type of data that can be stored in set_data_info:

[{
    type: "jank",
    info: [{
        path: '/components/cms/NewJewel/new-jewel', // Component or page path
        duration: 100,
        size: 100,
        paths: ['locationInfo', 'gpsInfo', 'shop']
    }]
},{
    type: "stutter",
    info: {
        path: '/components/cms/NewJewel/new-jewel', // Component or page path
        duration: 100,
        size: 100,
        paths: ['locationInfo', 'gpsInfo', 'shop']
    }
}]
Copy the code

The code monitored by setData can be written into Behavior, which can be used by both components and pages. Because pages can also be created using the Component constructor, only special components are used, and the attached events in behaviors will also be executed in the page. Can trigger setUpdatePerformanceListener in attached events.

The general idea is to initialize data (temporarily store performance monitoring data) in the onShow event of the Behavior monitoring page, report data in onHide, and monitor data in attached events.

this.setUpdatePerformanceListener({ withDataPaths: true }, (res: any) = > {
    const { updateStartTimestamp, updateEndTimestamp, dataPaths } = res
    const time: number = updateEndTimestamp - updateStartTimestamp
    const data: Record<string, any> = dataPaths.map((keys: string) = > {
        if (keys.length > 1) {
            let attribute = ' '
            let { data } = this

            for (const k of keys) {
                attribute += isNumber(k) ? ` [${k}] ` : `.${k}`
                data = data[k]
            }

            return {
                [attribute.substring(1)]: data,
            }
        }
        return {[keys]: this.data[keys]}
    })
    const size: number = JSON.stringify(data).length            
})
Copy the code

Report the strategy

Performance data monitoring should also be reported. Performance monitoring should not cause performance problems, so it should affect users as little as possible, as long as enough data can be collected for analysis. Therefore, we have two strategies:

  1. The interface controls whether to enable performance monitoring.
  2. Through special matching deviceId to control the number of users;

Controls whether to enable performance monitoring

Data prepull can be used to configure the performance monitoring switch data. Prepull can pull the business data from the third-party server in advance through the wechat background when the small program is cold started. When the code package is loaded, the page can be rendered more quickly, reducing the user waiting time, and thus improving the opening speed of the small program.

wx.setBackgroundFetchToken({ token: 'performence' })
  wx.getBackgroundFetchData({
      fetchType: 'pre'.success(res: Record<string, any>) {
          if(res? .fetchedData) {const config: {
                  version: string
                  percent: number
                  enable: boolean
                  whiteList: number[]
              } = JSON.parse(res.fetchedData)
          }
      },
  })
Copy the code

User proportional control

We didn’t want all users to report, so we thought of converting deviceId to a number that had a specific trailing digit, like 9.

DeviceId in the applet is also a randomly generated string. First, you need to convert the hash value to a number, and then match the last number.

const hashCode = function(str) {
  var hash = 0, i, chr;
  if (str.length === 0) return hash;
  for (i = 0; i < str.length; i++) {
    chr   = str.charCodeAt(i);
    hash  = ((hash << 5) - hash) + chr;
    hash |= 0;
  }
  return hash;
};

hashCode('f87dbddc-af21-479d-ac4b-30f0bb587ddf') / / 1842283027
Copy the code

conclusion

Through the above three schemes, we basically established our own small program performance monitoring, especially the performance monitoring of setData, so that we have the direction of promoting setData performance optimization, in the implementation can also define a number of setData frequency and data size indicators, first eliminate serious lag, gradually adjust the indicators, Achieve a better experience.