WebWorker berechnet langsame Regexp-Übereinstimmungen deutlich langsamer (3x) - nur Firefox


85

Zuerst habe ich mir einen regulären Ausdruck erstellt, der mit allen eindeutigen externen Bibliothekspfaden in einer Liste aller Header-Dateien in einem Projekt übereinstimmt. Ich habe vor einer Woche eine Frage zu diesem regulären Ausdruck gestellt .

Ich fing an, mich einzumischen, um zu sehen, wie es sich verhalten würde, wenn es asynchron ist und sich in einen Web-Worker verwandelt. Aus Gründen der Benutzerfreundlichkeit und Zuverlässigkeit habe ich diese universelle Datei erstellt, die in allen drei Modi ausgeführt wird:

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

Ich habe eine Testdatei erstellt, anstatt sie hier einzufügen. Ich habe sie auf ein sehr zuverlässiges Webhosting hochgeladen: Demo - Testdaten .

Was ich sehr überraschend finde, ist, dass es einen so signifikanten Unterschied zwischen der Ausführung von RegExp durch Webworker und Browser gibt. Die Ergebnisse, die ich bekam:

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

Sie können auch sehen, dass bei meinem speziellen regulären Ausdruck der Unterschied zwischen einer synchronen und einer asynchronen Schleife unbedeutend ist. Ich habe versucht, eine Übereinstimmungsliste anstelle eines Lookahead-Ausdrucks zu verwenden, und die Ergebnisse haben sich stark geändert. Hier sind die Änderungen an der alten Funktion:

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

Und die Ergebnisse:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:0.062s
    • [WORKER-SYNC]: Time elapsed:0.023s
    • [TIMEOUT]: Time elapsed:12.250s (Hinweis für sich selbst: Mit jeder Minute wird es seltsamer)
    • [LOOP]: Time elapsed:0.006s

Kann jemand einen solchen Geschwindigkeitsunterschied erklären?


6
Wenn Sie einen Firefox-Fehler dafür eingereicht haben, können Sie bitte die Fehler-URL zu Ihrer Frage hinzufügen? Und wenn Sie noch keinen Firefox-Fehler dafür gemeldet haben, können Sie sich bitte Zeit dafür nehmen.
Sideshowbarker

@sideshowbarker Ich habe gegoogelt, wo Firefox-Fehler gemeldet werden sollen, und bin gescheitert. Also füllte ich die Beschwerde "Ich kann nicht finden, wo ich Fehler melden kann " über Firefox-Eingaben (" Firefox hat mich traurig gemacht. ") Und gab auf. Wenn Sie wissen, wo Sie Fehler melden müssen (und es sich um das tatsächliche Meldeverfahren handelt, nicht um eine Senke für Benutzer-Feedback), teilen Sie mir dies bitte mit. Dies wäre nicht das erste Mal, dass ich ein Problem fand, das ich zuverlässig reproduzieren und als Nur-Firefox identifizieren konnte.
Tomáš Zato - Wiedereinsetzung Monica

1
Yeah stimmte zu, dass sie es nicht so klar machen, wie es sein könnte. Verwenden Sie für diesen speziellen Fehler auf jedenDOM: Workers Fall bugzilla.mozilla.org/… Core. Dadurch wird es gegen die entsprechende Bugzilla-Komponente im entsprechenden Bugzilla- Produkt ausgelöst .
Sideshowbarker

1
Um zu versuchen , Hilfe andere Menschen die gleichen Frustrationen vermeiden Sie lief in mit dem Versuch , herauszufinden , wo Firefox - Browser-Engine Fehler zu melden, habe ich stackoverflow.com/questions/33059442/... Wenn Sie denken , ist es nützlich , dass Informationen in den Akten zu haben , hier in StackOverflow, bitte überlegen Sie, ob Sie es abstimmen möchten (andernfalls besteht die Gefahr, dass es gelöscht wird, wenn andere knifflige Downvoter auf den Zug springen).
Sideshowbarker

1
Das Muster ist absichtlich langsam. Eine viel effizientere Möglichkeit besteht darin, die Lookaheads zu überspringen und stattdessen das Referenzarray zu verwenden. Bei dieser Frage geht es jedoch nicht darum, optimalen Code zu schreiben.
Tomáš Zato - Wiedereinsetzung Monica

Antworten:


2

Nach einer Reihe von Tests habe ich bestätigt, dass dies ein Mozilla Firefox- Problem ist (es betrifft alle Windows-Desktop-Versionen, die ich ausprobiert habe). Mit Google Chrome, Opera oder sogar Firefox Mobile dauern die regulären Ausdrucke ungefähr gleich, ob Worker oder nicht.

Wenn Sie dieses Problem beheben müssen, stimmen Sie unbedingt über den Fehlerbericht über Bugzilla ab . Ich werde versuchen, zusätzliche Informationen hinzuzufügen, wenn sich etwas ändert.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.