programing

WebWorker는 느린 regexp 일치를 상당히 느리게 (3x) 계산합니다.

nasanasas 2020. 9. 17. 07:57
반응형

WebWorker는 느린 regexp 일치를 상당히 느리게 (3x) 계산합니다.


먼저 프로젝트의 모든 헤더 파일 목록에서 모든 고유 한 외부 라이브러리 경로와 일치하는 정규식을 직접 만들었습니다. 일주일 전에 정규 표현식을 만드는 것에 대해 질문 했습니다.

비동기식 일 때와 웹 작업자가 될 때 어떻게 동작하는지 알아보기 위해 개입하기 시작했습니다. 편의성과 안정성을 위해 세 가지 모드 모두에서 실행되는이 범용 파일을 만들었습니다.

/** Will call result() callback with every match it founds. Asynchronous unless called 
 *  with interval = -1.
 *  Javadoc style comment for Arnold Rimmer and other Java programmers:
 *  
 * @param regex regular expression to match in string
 * @param string guess what
 * @param result callback function that accepts one parameter, string match
 * @param done callback on finish, has no parameters
 * @param interval delay (not actual interval) between finding matches. If -1, 
 *        function  will be blocking
 * @property working false if loop isn't running, otherwise contains timeout ID
 *           for use with clearTimeout
 * @property done copy of done parameter
 * @throws heavy boulders
**/
function processRegex(regex, string, result, done, interval) {
  var m;
  //Please tell me interpreter optimizes this
  interval = typeof interval!='number'?1:interval;
  //And this
  processRegex.done = done;
  while ((m = regex.exec(string))) {
    Array.prototype.splice.call(m,0,1);
    var path = m.join("");
    //It's good to keep in mind that result() slows down the process
    result(path);
    if (interval>=0) {
      processRegex.working = setTimeout(processRegex, 
                              interval, regex, string, 
                              result, done, interval);
      // Comment these out for maximum speed
      processRegex.progress = regex.lastIndex/string.length;
      console.log("Progress: "+Math.round(processRegex.progress*100)+"%");
      return;
    }
  }

  processRegex.working = false;
  processRegex.done = null;
  if (typeof done=="function")
    done();
}
processRegex.working = false; 

여기에 붙여 넣는 대신 테스트 파일을 만들었습니다. 매우 안정적인 웹 호스팅 인 Demo - Test data 에 업로드했습니다 .

제가 매우 놀라운 사실은 웹 작업자와 RegExp의 브라우저 실행간에 큰 차이가 있다는 것입니다. 내가 얻은 결과 :

  • 모질라 파이어 폭스
    • [WORKER]: Time elapsed:16.860s
    • [WORKER-SYNC]: Time elapsed:16.739s
    • [TIMEOUT]: Time elapsed:5.186s
    • [LOOP]: Time elapsed:5.028s

You can also see that with my particular regular expression, the difference between a synchronous and an asynchronous loop is insignificant. I tried to use a match list instead of a lookahead expression and the results changed a lot. Here are the changes to the old function:

function processRegexUnique(regex, string, result, done, interval) {
  var matchList = arguments[5]||[];
  ... same as before ...
  while ((m = regex.exec(string))) {
    ... same as before ...
    if (matchList.indexOf(path)==-1) {
      result(path);
      matchList.push(path);
    }
    if (interval>=0) {
      processRegex.working = setTimeout(processRegex, interval, 
                               regex, string, result, 
                               done, interval, matchList);
      ... same as before ...
    }
  }
  ... same as before ...
}

And the results:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:0.062s
    • [WORKER-SYNC]: Time elapsed:0.023s
    • [TIMEOUT]: Time elapsed:12.250s (note to self: it's getting weirder every minute)
    • [LOOP]: Time elapsed:0.006s

Can anyone explain such a difference in speed?


After a series of tests, I confirmed that this is a Mozilla Firefox issue (it affects all windows desktop versions I tried). With Google Chrome, Opera, or even Firefox mobile, the regexp matches take about the same, worker or not.

If you need this issue fixed, be sure to vote on bug report on bugzilla. I will try to add additional information if anything changes.

참고URL : https://stackoverflow.com/questions/32910126/webworker-calculates-slow-regexp-matches-significantly-slower-3x-firefox-onl

반응형