WebWorker обчислює збіги повільних регулярних виразів значно повільніше (3 рази) - лише для Firefox


85

Спочатку я просто створив собі регулярний вираз, який буде відповідати всім унікальним шляхам зовнішньої бібліотеки у списку всіх файлів заголовків у проекті. Я задав питання щодо створення цього регулярного виразу тиждень тому.

Я почав втручатися, щоб побачити, як це буде поводитися, коли буде асинхронно, а коли перетвориться на веб-працівника. Для зручності та надійності я створив цей універсальний файл, який працює у всіх трьох режимах:

/** 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 - тестові дані .

Що мене дуже дивує, так це те, що існує така суттєва різниця між веб-працівником та виконанням RegExp у браузері. Результати, які я отримав:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:16.860s
    • [WORKER-SYNC]: Time elapsed:16.739s
    • [TIMEOUT]: Time elapsed:5.186s
    • [LOOP]: Time elapsed:5.028s

Ви також можете бачити, що з моїм конкретним регулярним виразом різниця між синхронним та асинхронним циклом незначна. Я намагався використовувати список відповідності замість виразу lookahead, і результати сильно змінилися. Ось зміни до старої функції:

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 ...
}

І результати:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:0.062s
    • [WORKER-SYNC]: Time elapsed:0.023s
    • [TIMEOUT]: Time elapsed:12.250s (зверніть увагу на себе: щохвилини стає дивнішим)
    • [LOOP]: Time elapsed:0.006s

Хтось може пояснити таку різницю в швидкості?


6
Якщо ви подали помилку Firefox для цього, чи можете ви, будь ласка, додати URL-адресу помилки до свого запитання? І якщо ви ще не подали помилку для Firefox, сподіваюся, ви можете подумати про те, щоб витратити час на це.
SideShowBarker

@sideshowbarker Я погуглив, де повідомити про помилки firefox, і мені не вдалося. Тож я заповнив скаргу " Не можу знайти, де повідомити про помилки " на введенні в Firefox (" Firefox мене засмутив ") і відмовився. Якщо ви знаєте, де повідомляти про помилки (і це фактична процедура звітування, а не деяка помилка для відгуків користувачів), будь ласка, скажіть мені. Це було не вперше, коли я виявив проблему, яку я міг надійно відтворити та визначити лише для Firefox.
Томаш Зато - відновити Моніку

1
Так, погодились, що вони не роблять це настільки чітко, наскільки це може бути. У будь-якому випадку, для цієї конкретної помилки, будь ласка, використовуйте bugzilla.mozilla.org/ ... Це підніме її до відповідного DOM: Workersкомпонента bugzilla у відповідному Coreпродукті bugzilla .
SideShowBarker

1
Щоб спробувати допомогти іншим людям уникнути тих самих розчарувань, з якими ви зіткнулися, намагаючись з'ясувати, де повідомляти про помилки браузера Firefox, я створив stackoverflow.com/questions/33059442/ ... Якщо ви вважаєте, що корисно мати таку інформацію тут, у StackOverflow, будь ласка, подумайте проголосувати за нього (інакше це може загрожувати видаленню, якщо інші прихильники головної боротьби, що закривають все-все, стрибають на перегони).
SideShowBarker

1
Візерунок навмисне повільний. Набагато ефективніший спосіб це пропустити підстановки та використовувати замість них референсний масив. Але це питання насправді не стосується написання оптимального коду.
Томаш Зато - відновити Моніку

Відповіді:


2

Після низки тестів я підтвердив, що це проблема Mozilla Firefox (вона впливає на всі версії настільних комп'ютерів Windows, які я пробував). У Google Chrome, Opera або навіть Firefox для мобільних пристроїв збіги регулярних виразів займають приблизно те саме, робочий чи ні.

Якщо вам потрібно вирішити цю проблему, обов’язково проголосуйте за звіт про помилки на bugzilla . Я спробую додати додаткову інформацію, якщо щось зміниться.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.