Front end page rendering optimization -- performance tool analysis and optimization

Posted by vishi83 on Thu, 13 Jan 2022 14:44:40 +0100

First of all, this is a code run to calculate the optimization of a large number of logic.

(1) Scene

  1. When there is a lot of logical calculation of data in JS
  2. Non static resource optimization
  3. Code level optimization

(2) Tools

The performance of Chrome Devtools can be found by pressing F12 in the browser.

(3) Situation

When our page is carrying out a large number of data logical operations, our page will not start rendering until the data calculation is completed. First of all, this is because page rendering is a macro task in our task task. The main task of the main thread also needs to calculate js, so it causes blocking.

(4) We create a page with the following code

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Not optimized</title>
</head>
<body>
        
    <script>
        let t1, t2 = 0
        t1 = new Date() // The page starts loading
        window.onload = (event) => {
            t2 = new Date() // Page loading completed
            console.log(`Time taken after page loading: ${t2 - t1}ms`)
        }
    </script>
    <script>
        const a = () => {
            b()
        }

        const b = () => {
            let total = 0
            for(let i = 0; i < 10*10000*10000; i++) {
                total += i
            }
            console.log('1 : ', total)
        }

        a()
    </script>

    <script>
        const c = () => {
            d()
        }
        const d = () => {
            let total = 0
            for(let i = 0; i < 10*10000*10000; i++) {
                total += i
            }
            console.log('2 : ', total)
        }

        c()
    </script>
</body>
</html>

analysis

  1. Page loading time:
// Console output:
1 :  499999999067109000
2 :  499999999067109000
 Time taken after page loading: 3065ms
  1. Analysis through performance tools

    It is found that there are two long tasks in the task macro task of the main thread. It is these long tasks that cause the blocking state when the page is rendered.

We can check the corresponding source code:

These are the running time of our code. We found the code that has been running for a long time, that is, the b function and d function corresponding to long task. Now we can quickly load our pages as long as we eliminate them.

(5) Start optimization

  1. Instead of running our functions on the main thread, use the worker thread to run
  2. Make full use of multithreading

code:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>After optimization</title>
</head>
<body>

    <script>
        let t1, t2 = 0
        t1 = new Date() // The page starts loading
        window.onload = (event) => {
            t2 = new Date() // Page loading completed
            console.log(`Time taken after page loading: ${t2 - t1}ms`)
        }
    </script>

    <script>
        // Using worker thread optimization promise to encapsulate postMessage is to pass parameters asynchronously
        const runWorker = (url, num) => {
            return new Promise((resolve, reject) => {
                const worker = new Worker(url)
                worker.postMessage(num)
                worker.onmessage = (evt) => {
                    resolve(evt.data)
                }
                worker.onerror = reject
            })
            
        }
    </script>
    
    <script>
        const a = () => {
            b()
        }
        const b = () => {
            // Give the data logic processing process before the b function to the worker JS thread to handle the message event
            runWorker('./worker.js', 10*10000*10000).then(res => {
                console.log('res 01: ', res)
            }).catch(err => {
                console.log('err 01: ', err)
            })
        }
        a()
    </script>

    <script>
        const c = () => {
            d()
        }
        const d = () => {
            // Give the data logic processing process before the d function to worker02 JS thread to handle the message event
            runWorker('./worker02.js', 10*10000*10000).then(res => {
                console.log('res 02: ', res)
            }).catch(err => {
                console.log('err 02: ', err)
            })
        }
        c()
    </script>
</body>
</html>

worker.js and worker02 JS is responsible for writing our computing logic

// Here write the processing logic of the b function

addEventListener('message', (evt) => {
    console.log(evt)
    let total = 0, num = evt.data
    for (let i = 0; i < num; i++) {
        total += i
    }
    console.log('worker.js 01 : ', total)
    // Finally, you can send the result back to postMessage
    postMessage(total)
})

Open the console to view:

  1. Time after page loading:
Time taken after page loading: 22ms
  1. Analysis with performance tool

The long task s of our main thread have disappeared. They are running on the worker thread, so it will not affect our page rendering.

summary

  1. The long task of the Main thread is eliminated, which is reduced from more than 3000 milliseconds to more than 20 milliseconds
  2. worker threads make full use of the role of multithreading
  3. When page rendering parses HTML, it is a macro task
  4. Master the common functions of performance

The source code is on GitHub: Get the source code here

Topics: Javascript Front-end Optimize performance