Angular Debugging - A real bug caused by multiple loops

The cause of performance problems can be complex or simple, let's look at a real-life example today. A multiple loop caused the list to freeze. 

startDemo() {
    this.processing = true
    // 创建复杂数据结构
    const data = [];
    for (let i = 0; i < 5000; i++) {
      const innerArray = [];
      for (let j = 0; j < 5000; j++) {
        const innerObject:any = {};
        innerObject.value = Math.random();
        innerArray.push(innerObject);
      }
      data.push(innerArray);
    }

    // 循环嵌套循环处理数据
    _.forEach(data, (innerArray) => {
      _.forEach(innerArray, (innerObject) => {
        innerObject.value = Math.pow(innerObject.value, 2);
      });
      innerArray = _.sortBy(innerArray, 'value');
    });

    // 模拟延迟以增加计算量
    setTimeout(() => {
      this.processing = false
    }, 2000);
  }

Demonstration result:

The problem causing the browser to crash is:

First, a very large data structure is created with 5000 internal arrays of 5000 objects each. This will take up a lot of memory.

The data is then processed in two nested forEach loops. For such a large-scale data structure, this would result in a very high computational load, consuming a lot of CPU resources and time.

Next, setTimeout is used in the delayed operation, which delays the operation by 2 seconds. Although this is meant to simulate a long running process, during this time the browser will be under a lot of stress and may become unresponsive or crash

How to optimize it:

1. Reduce the data size: Since the data size is very large, you can consider reducing the number of internal arrays or the number of objects to reduce memory usage and calculation load.

2. Batch processing: Process data in batches instead of processing the entire data structure at once. You can use paging or chunking to process a part of the data at a time, and then wait for a period of time before processing the next part of the data. This can avoid the impact of long-term single computing tasks on the browser.

3. Use Web Workers: Put data processing and sorting operations in Web Workers. Web Worker can execute code in a background thread to avoid blocking the main thread, thereby improving the responsiveness of the browser.

4. Optimize algorithms and data structures: If possible, consider using more efficient algorithms and data structures for data processing and sorting to reduce computational complexity and improve performance.

Optimized demo: (The processing method uses batch processing)

startProcessing() {
    this.processing = true;
    this.currentPage = 0;

    this.data = [];
    for (let i = 0; i < 5000; i++) {
      const innerArray = [];
      for (let j = 0; j < 5000; j++) {
        const innerObject:any = {};
        innerObject.value = Math.random();
        innerArray.push(innerObject);
      }
      this.data.push(innerArray);
    }

    const pageSize = 100;
    this.numPages = Math.ceil(this.data.length / pageSize);

    const processPage = () => {
      const start = this.currentPage * pageSize;
      const end = Math.min((this.currentPage + 1) * pageSize, this.data.length);
      const pageData = this.data.slice(start, end);

      _.forEach(pageData, (innerArray) => {
        _.forEach(innerArray, (innerObject) => {
          innerObject.value = Math.pow(innerObject.value, 2);
        });

        innerArray = _.sortBy(innerArray, 'value');
      });

      this.currentPage++;

      if (this.currentPage < this.numPages) {
        setTimeout(processPage, 0);
      } else {
        this.processing = false;
      }
    };

    setTimeout(processPage, 0);
  }

 

 Although it is a simple and low-level error, errors are actually happening around you. When the amount of data is small, there may be no difference in any writing method. As your project grows, problems are gradually exposed and can only be solved one by one.

 

 

 

Guess you like

Origin blog.csdn.net/KenkoTech/article/details/131443109