WebWorker calcula coincidencias de expresiones regulares lentas significativamente más lentas (3x) - solo Firefox

85

Primero, acabo de crearme una expresión regular que coincidirá con todas las rutas de biblioteca externas únicas en una lista de todos los archivos de encabezado de un proyecto. Hice una pregunta sobre cómo hacer esa expresión regular hace una semana.

Comencé a entrometerme para ver cómo se comportaría cuando fuera asincrónico y cuando se convirtiera en un trabajador web. Por conveniencia y confiabilidad, creé este archivo universal que se ejecuta en los tres modos:

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

Creé un archivo de prueba, en lugar de pegarlo aquí, lo cargué en un alojamiento web muy confiable: Demo - Datos de prueba .

Lo que encuentro muy sorprendente es que existe una diferencia tan significativa entre el trabajador web y la ejecución del navegador de RegExp. Los resultados que obtuve:

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

También puede ver que con mi expresión regular particular, la diferencia entre un bucle sincrónico y asincrónico es insignificante. Intenté utilizar una lista de coincidencias en lugar de una expresión anticipada y los resultados cambiaron mucho. Aquí están los cambios a la función anterior:

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

Y los resultados:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:0.062s
    • [WORKER-SYNC]: Time elapsed:0.023s
    • [TIMEOUT]: Time elapsed:12.250s (nota para mí mismo: se vuelve más extraño cada minuto)
    • [LOOP]: Time elapsed:0.006s

¿Alguien puede explicar tal diferencia de velocidad?

Tomáš Zato - Reincorporar a Monica
fuente
6
Si ha presentado un error de Firefox para esto, ¿puede agregar la URL del error a su pregunta? Y si aún no ha presentado un error de Firefox, espero que pueda considerar tomarse el tiempo para hacerlo.
sideshowbarker
@sideshowbarker Busqué en Google dónde informar errores de Firefox y fallé. Así que llené la queja " No puedo encontrar dónde informar errores " en la entrada de Firefox (" Firefox me entristeció ") y me rendí . Si sabe dónde informar errores (y es un procedimiento de informe real, no un receptor de comentarios de los usuarios), por favor dígame. Esta no sería la primera vez que encontré un problema que podría reproducir e identificar de manera confiable como solo para Firefox.
Tomáš Zato - Reincorpora a Monica
1
Sí, acordó que no lo dejan tan claro como podría ser. De todos modos, para este error en particular, utilice bugzilla.mozilla.org/…. Eso lo generará contra el DOM: Workerscomponente bugzilla apropiado en el Coreproducto bugzilla apropiado .
sideshowbarker
1
Para tratar de ayudar a otras personas a evitar las mismas frustraciones con las que se encontró al tratar de averiguar dónde informar los errores del motor del navegador de Firefox, creé stackoverflow.com/questions/33059442/ ... Si cree que es útil tener esa información registrada aquí en StackOverflow, por favor considere votarlo a favor (de lo contrario, puede correr el riesgo de ser eliminado si otros votantes negativos que se suben al tren).
sideshowbarker
1
El patrón es lento a propósito. Una forma mucho más eficiente de hacerlo es omitir las búsquedas anticipadas y usar una matriz de referencia en su lugar. Pero esta pregunta realmente no se trata de escribir un código óptimo.
Tomáš Zato - Reincorporación a Monica

Respuestas:

2

Después de una serie de pruebas, confirmé que se trata de un problema de Mozilla Firefox (afecta a todas las versiones de escritorio de Windows que probé). Con Google Chrome, Opera o incluso Firefox para dispositivos móviles, las coincidencias de expresiones regulares toman aproximadamente lo mismo, trabajador o no.

Si necesita que se solucione este problema, asegúrese de votar el informe de error en bugzilla . Intentaré agregar información adicional si algo cambia.

Tomáš Zato - Reincorporar a Monica
fuente