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; 

Я создал тестовый файл, вместо того, чтобы вставить его сюда, я загрузил его на очень надежный веб-хостинг: Демо - Тестовые данные .

Что меня очень удивляет, так это то, что существует такая значительная разница между исполнением RegExp в веб-воркере и браузером. В результате я получил:

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

Вы также можете видеть, что с моим конкретным регулярным выражением разница между синхронным и асинхронным циклом незначительна. Я попытался использовать список соответствий вместо выражения просмотра вперед, и результаты сильно изменились. Вот изменения в старой функции:

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 Я искал в Google, где сообщать об ошибках Firefox, и мне это не удалось. Поэтому я заполнил жалобу « Не могу найти, где сообщить об ошибках » на вводе FirefoxFirefox меня огорчил ») и сдался. Если вы знаете, куда сообщать об ошибках (и это фактическая процедура сообщения, а не какой-то приемник для отзывов пользователей), сообщите мне. Это не первый раз, когда я обнаруживаю проблему, которую я могу надежно воспроизвести и идентифицировать только как firefox.
Томаш Зато - Восстановите Монику
1
Да, согласен, они не разъясняют это так ясно, как могло бы быть. В любом случае, для этой конкретной ошибки используйте bugzilla.mozilla.org/ ... Это повысит ее соответствие с соответствующим DOM: Workersкомпонентом bugzilla в соответствующем Coreпродукте bugzilla .
sideshowbarker
1
Чтобы попытаться помочь другим людям избежать тех же разочарований, с которыми вы столкнулись, пытаясь выяснить, где сообщать об ошибках в браузере Firefox, я создал stackoverflow.com/questions/33059442/. Если вы считаете, что полезно записать эту информацию здесь, в StackOverflow, пожалуйста, подумайте о том, чтобы проголосовать за него (в противном случае он может быть удален, если на подножку подпрыгнут другие сторонники, решившие закрыть все дела).
Sideshowbarker
1
Шаблон медленный намеренно. Гораздо более эффективный способ сделать это - пропустить просмотр вперед и вместо этого использовать массив ссылок. Но на самом деле этот вопрос не о написании оптимального кода.
Tomáš Zato - Reinstate Monica

Ответы:

2

После серии тестов я подтвердил, что это проблема Mozilla Firefox (она затрагивает все версии Windows для настольных компьютеров, которые я пробовал). В Google Chrome, Opera или даже Firefox для мобильных устройств совпадения регулярных выражений занимают примерно одно и то же время, будь то рабочий или нет.

Если вам нужно исправить эту проблему, не забудьте проголосовать за отчет об ошибке на bugzilla . Если что-то изменится, я постараюсь добавить дополнительную информацию.

Томаш Зато - Восстановить Монику
источник