ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • javascript - 자바 스크립트에서 오래 실행되는 함수를 분해하지만 성능을 유지하는 방법
    front개발 2021. 11. 16. 11:34
    728x90
    반응형
    장기 실행 기능이 있습니다. 큰 배열을 반복하고 각 루프 내에서 기능을 수행합니다.

    longFunction : function(){
           var self = this;
           var data = self.data;
    
           for(var i=0; len = data.length; i<len; i++){
                  self.smallFunction(i);
           }
    },
    smallFunction : function(index){
    
    // Do Stuff!
    
    }
    


    대부분의 경우 이것은 괜찮지 만 약 1500 이상의 배열을 처리 할 때 자바 스크립트 실행 경고 메시지를받을 수 있습니다.

    그래서 나는 이것을 분해해야합니다. 나의 첫 번째 시도는 다음과 같습니다 :

    longFunction : function(index){
           var self = this;
           var data = self.data;
    
    
          self.smallFunction(index);
    
          if(data.slides[index+1){
             setTimeout(function(){
                self.longFunction(index+1);
             },0);
          }
          else {
                   //WORK FINISHED
          }
    
    },
    smallFunction : function(index){
    
    // Do Stuff!
    
    }
    


    그래서 루프를 제거하고 각 반복마다 인덱스를 증가시키는 자체 호출 기능을 소개합니다. 자바 스크립트 실행 경고 방법을 방지하기 위해 기본 UI 스레드로 제어를 반환하기 위해 각 반복 후에 업데이트 할 시간을 허용하기 위해 setTimeout를 추가했습니다. 문제는이 방법을 사용하면 실제 작업을 수행하는 데 문자 그대로 10 배 더 오래 걸립니다. setTimeout가 0으로 설정되어 있지만 실제로는 10ms보다 더 기다리고 있습니다. 대형 어레이에서 매우 빠르게 구축됩니다. setTimeout를 제거하고 longFunction 호출 자체를 허용하면 원래 루프 방법과 비슷한 성능을 제공합니다.

    루프와 비슷한 성능을 가지고 있지만 자바 스크립트 실행 경고를 발생시키지 않는 다른 솔루션이 필요합니다. 불행히도이 인스턴스에서는 webWorkers를 사용할 수 없습니다.

    이 과정에서 완전히 반응하는 UI가 필요하지 않습니다. 몇 초마다 진행률 표시 줄을 업데이트하기에 충분합니다.

    루프 덩어리로 나누는 것이 옵션입니까? 즉 한 번에 500 회 반복 수행, 중지, 시간 초과, 진행률 표시 줄 업데이트, 다음 500 번 수행 등.

    더 좋은 것이 있습니까?

    대답:

    유일한 해결책은 작업을 중단시키는 것 같습니다.

    내 자체 호출 기능에 다음을 추가하여 250 반복마다 UI를 업데이트 할 수 있습니다.

     longFunction : function(index){
               var self = this;
               var data = self.data;
    
    
              self.smallFunction(index);
    
              var nextindex = i+1;
    
              if(data.slides[nextindex){
                if(nextindex % 250 === 0){
                 setTimeout(function(){               
                    self.longFunction(nextindex);
                 },0);
                }
                else {
                    self.longFunction(nextindex);
                }
              }
              else {
                       //WORK FINISHED
              }
    
        },
        smallFunction : function(index){
    
        // Do Stuff!
    
        }
    


    내가하고있는 일은 다음 인덱스가 250으로 나눌 수 있는지 확인하는 것입니다. 그렇다면 타임 아웃을 사용하여 기본 UI 스레드를 업데이트 할 수 있습니다. 그렇지 않으면 다시 직접 호출합니다. 문제 해결됨!
    다음은 내가 작성한 이전 답변에서 수정 된 배치 코드입니다.

    var n = 0,
        max = data.length;
        batch = 100;
    
    (function nextBatch() {
        for (var i = 0; i < batch && n < max; ++i, ++n) {
            myFunc(n);
        }
        if (n < max) {
            setTimeout(nextBatch, 0);
        }
    })();
    

    이 질문에 대해 Stack Overflow에서 비슷한 토론을 찾았습니다: https://stackoverflow.com/questions/16353240/

    728x90
    반응형
Designed by Tistory.