WebWorker oblicza powolne dopasowania wyrażeń regularnych znacznie wolniej (3x) - tylko Firefox


85

Najpierw stworzyłem sobie wyrażenie regularne, które będzie pasowało do wszystkich unikalnych ścieżek bibliotek zewnętrznych na liście wszystkich plików nagłówkowych w projekcie. Tydzień temu zadałem pytanie dotyczące tworzenia tego wyrażenia regularnego .

Zacząłem się wtrącać, aby zobaczyć, jak będzie się zachowywał, gdy będzie asynchroniczny i gdy zostanie przekształcony w pracownika internetowego. Dla wygody i niezawodności stworzyłem ten uniwersalny plik, który działa we wszystkich trzech trybach:

/** 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; 

Stworzyłem plik testowy, zamiast go wkleić tutaj, wrzuciłem go na bardzo niezawodny hosting: Demo - Dane testowe .

To, co uważam za bardzo zaskakujące, to fakt, że istnieje tak znacząca różnica między narzędziem roboczym sieci Web a wykonywaniem RegExp w przeglądarce. Wyniki, które otrzymałem:

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

Możesz również zobaczyć, że w moim konkretnym wyrażeniu regularnym różnica między pętlą synchroniczną i asynchroniczną jest nieistotna. Próbowałem użyć listy dopasowań zamiast wyrażenia lookahead i wyniki bardzo się zmieniły. Oto zmiany w starej funkcji:

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

A wyniki:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:0.062s
    • [WORKER-SYNC]: Time elapsed:0.023s
    • [TIMEOUT]: Time elapsed:12.250s (uwaga dla siebie: z każdą minutą robi się coraz dziwniej)
    • [LOOP]: Time elapsed:0.006s

Czy ktoś może wyjaśnić taką różnicę w szybkości?


6
Jeśli zgłosiłeś błąd w Firefoksie, czy możesz dodać adres URL błędu do swojego pytania? A jeśli jeszcze nie zgłosiłeś błędu Firefoksa, mam nadzieję, że możesz rozważyć poświęcenie na to czasu.
sideshowbarker

@sideshowbarker Wygooglowałem, gdzie zgłosić błędy Firefoksa i nie udało mi się. Wypełniłem więc skargę „ Nie mogę znaleźć miejsca zgłaszania błędów ” na wejściu Firefoksa („ Firefox mnie zasmucił ”) i zrezygnowałem. Jeśli wiesz, gdzie zgłaszać błędy (i jest to faktyczna procedura zgłaszania, a nie jakiś zlew do opinii użytkowników), powiedz mi. To nie byłby pierwszy raz, kiedy napotkałem problem, który mógłbym wiarygodnie odtworzyć i zidentyfikować jako tylko firefox.
Tomáš Zato - Przywróć Monikę

1
Tak, zgodzili się, że nie wyjaśniają tego tak jasno, jak mogłoby to być. W każdym razie, w przypadku tego konkretnego błędu, proszę użyć bugzilla.mozilla.org/… To podniesie go do odpowiedniego DOM: Workersskładnika bugzilla w odpowiednim Coreprodukcie bugzilla .
sideshowbarker

1
Aby pomóc innym ludziom uniknąć tych samych frustracji, które napotkałeś, próbując dowiedzieć się, gdzie zgłaszać błędy silnika przeglądarki Firefox, utworzyłem stackoverflow.com/questions/33059442/ ... Jeśli uważasz, że warto mieć te informacje tutaj w StackOverflow, rozważ możliwość zagłosowania za nim (w przeciwnym razie może być zagrożone usunięciem, jeśli inni ścigający się na głucho downvoters wskoczą na modę).
Sidehowbarker

1
Wzór jest celowo powolny. O wiele bardziej efektywnym sposobem jest pominięcie wyprzedzeń i zamiast tego użycie tablicy referencyjnej. Ale to pytanie tak naprawdę nie dotyczy pisania optymalnego kodu.
Tomáš Zato - Przywróć Monikę

Odpowiedzi:


2

Po serii testów potwierdziłem, że jest to problem z Mozilla Firefox (dotyczy wszystkich wersji Windows na komputery, które wypróbowałem). W przypadku przeglądarki Google Chrome, Opera, a nawet mobilnej przeglądarki Firefox, dopasowania wyrażeń regularnych trwają mniej więcej tak samo, niezależnie od tego, czy plik roboczy czy nie.

Jeśli potrzebujesz rozwiązania tego problemu, pamiętaj, aby zagłosować na raport o błędzie w witrynie Bugzilla . Postaram się dodać dodatkowe informacje, jeśli coś się zmieni.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.