WebWorker calcola le corrispondenze regexp lente in modo significativamente più lento (3x) - solo Firefox


85

Per prima cosa ho creato io stesso un'espressione regolare che corrisponderà a tutti i percorsi di libreria esterna univoci in un elenco di tutti i file di intestazione in un progetto. Ho posto una domanda sulla creazione di quella regexp una settimana fa.

Ho iniziato a immischiarmi per vedere come si sarebbe comportato quando era asincrono e quando si trasformava in un web worker. Per comodità e affidabilità ho creato questo file universale che funziona in tutte e tre le modalità:

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

Ho creato un file di prova, invece di incollarlo qui l'ho caricato su un web hosting molto affidabile: Demo - Dati di prova .

Quello che trovo molto sorprendente è che c'è una differenza così significativa tra il web worker e l'esecuzione del browser di RegExp. I risultati che ho ottenuto:

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

Puoi anche vedere che con la mia particolare espressione regolare, la differenza tra un ciclo sincrono e un ciclo asincrono è insignificante. Ho provato a utilizzare un elenco di corrispondenze invece di un'espressione di lookahead ei risultati sono cambiati molto. Ecco le modifiche alla vecchia funzione:

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

E i risultati:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:0.062s
    • [WORKER-SYNC]: Time elapsed:0.023s
    • [TIMEOUT]: Time elapsed:12.250s (nota a me stesso: sta diventando più strano ogni minuto)
    • [LOOP]: Time elapsed:0.006s

Qualcuno può spiegare una tale differenza di velocità?


6
Se hai segnalato un bug di Firefox per questo, puoi aggiungere l'URL del bug alla tua domanda? E se non hai ancora segnalato un bug di Firefox, spero che tu possa prendere in considerazione l'idea di prenderti del tempo per farlo.
sideshowbarker

@sideshowbarker Ho cercato su Google dove segnalare i bug di Firefox e ho fallito. Così ho compilato il reclamo " Non riesco a trovare dove segnalare i bug " sull'input di Firefox (" Firefox mi ha reso triste. ") E ho rinunciato. Se sai dove segnalare i bug (ed è la procedura di segnalazione effettiva, non qualche pozzo per il feedback degli utenti), per favore dimmelo. Questa non sarebbe la prima volta che ho riscontrato un problema che potevo riprodurre e identificare in modo affidabile come solo Firefox.
Tomáš Zato - Ripristina Monica

1
Sì, d'accordo sul fatto che non lo rendono chiaro come potrebbe essere. Ad ogni modo, per questo particolare bug, per favore usa bugzilla.mozilla.org/… Questo lo solleverà contro il DOM: Workerscomponente bugzilla appropriato nel Coreprodotto bugzilla appropriato .
sideshowbarker

1
Per cercare di aiutare altre persone a evitare le stesse frustrazioni che hai incontrato cercando di capire dove segnalare i bug del motore del browser Firefox, ho creato stackoverflow.com/questions/33059442/… Se ritieni che sia utile avere queste informazioni registrate qui in StackOverflow, per favore valuta la possibilità di upvoting (altrimenti potrebbe essere a rischio di essere cancellato se altri downvoters impulsivi che chiudono tutte le cose saltano sul carrozzone).
sideshowbarker

1
Lo schema è lento di proposito. Un modo molto più efficiente per farlo è saltare i lookahead e utilizzare invece l'array di riferimento. Ma questa domanda non riguarda davvero la scrittura di codice ottimale.
Tomáš Zato - Ripristina Monica il

Risposte:


2

Dopo una serie di test, ho confermato che si tratta di un problema di Mozilla Firefox (interessa tutte le versioni desktop di Windows che ho provato). Con Google Chrome, Opera o anche Firefox mobile, le corrispondenze regexp richiedono più o meno lo stesso, lavoratore o meno.

Se hai bisogno di risolvere questo problema, assicurati di votare la segnalazione di bug su bugzilla . Cercherò di aggiungere ulteriori informazioni se qualcosa cambia.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.