WebWorker calcule les correspondances d'expression régulière lentes significativement plus lentes (3x) - Firefox uniquement


85

Tout d'abord, je viens de me créer une expression régulière qui correspondra à tous les chemins de bibliothèque externes uniques dans une liste de tous les fichiers d'en-tête d'un projet. J'ai posé une question concernant la création de cette expression rationnelle il y a une semaine.

J'ai commencé à me mêler pour voir comment il se comporterait lorsqu'il était asynchrone et transformé en travailleur Web. Pour plus de commodité et de fiabilité, j'ai créé ce fichier universel qui s'exécute dans les trois modes:

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

J'ai créé un fichier de test, plutôt que de le coller ici, je l'ai téléchargé sur un hébergement Web très fiable: Démo - Données de test .

Ce que je trouve très surprenant, c'est qu'il y a une telle différence significative entre l'exécution du web worker et du navigateur de RegExp. Les résultats que j'ai obtenus:

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

Vous pouvez également voir qu'avec mon expression régulière particulière, la différence entre une boucle synchrone et asynchrone est insignifiante. J'ai essayé d'utiliser une liste de correspondance au lieu d'une expression anticipée et les résultats ont beaucoup changé. Voici les modifications apportées à l'ancienne fonction:

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

Et les résultats:

  • Mozilla Firefox
    • [WORKER]: Time elapsed:0.062s
    • [WORKER-SYNC]: Time elapsed:0.023s
    • [TIMEOUT]: Time elapsed:12.250s (Note à moi-même: ça devient de plus en plus bizarre à chaque minute)
    • [LOOP]: Time elapsed:0.006s

Quelqu'un peut-il expliquer une telle différence de vitesse?


6
Si vous avez déposé un bogue Firefox pour cela, pouvez-vous ajouter l'URL du bogue à votre question? Et si vous n'avez pas encore déposé de bogue dans Firefox, j'espère que vous pouvez envisager de prendre le temps de le faire.
Sideshowbarker

@sideshowbarker J'ai cherché sur Google où signaler les bogues de Firefox et j'ai échoué. J'ai donc rempli la plainte " Impossible de trouver où signaler les bogues " sur l'entrée de Firefox (" Firefox m'a rendu triste. ") Et j'ai abandonné. Si vous savez où signaler les bogues (et c'est la procédure de rapport réelle, pas un puits pour les commentaires des utilisateurs), veuillez me le dire. Ce ne serait pas la première fois que je découvrais un problème que je pourrais reproduire et identifier de manière fiable comme étant uniquement Firefox.
Tomáš Zato - Réintégrer Monica

1
Oui, ils ont convenu qu'ils ne le faisaient pas aussi clairement que possible. Quoi qu'il en soit, pour ce bogue particulier, veuillez utiliser bugzilla.mozilla.org/ ... Cela le lèvera contre le DOM: Workerscomposant bugzilla approprié dans le Coreproduit bugzilla approprié .
Sideshowbarker

1
Pour essayer d'aider d'autres personnes à éviter les mêmes frustrations que celles que vous avez rencontrées en essayant de savoir où signaler les bogues du moteur de navigateur Firefox, j'ai créé stackoverflow.com/questions/33059442/ ... Si vous pensez qu'il est utile d'avoir ces informations enregistrées ici dans StackOverflow, veuillez envisager de voter à la hausse (sinon, il peut être à risque d'être supprimé si d'autres électeurs à la dérive qui ferment tout les choses sautent dans le train).
Sideshowbarker

1
Le motif est volontairement lent. Une manière beaucoup plus efficace de faire est de sauter les lookaheads et d'utiliser le tableau de référence à la place. Mais cette question ne concerne pas vraiment l'écriture de code optimal.
Tomáš Zato - Réintégrer Monica

Réponses:


2

Après une série de tests, j'ai confirmé qu'il s'agissait d' un problème de Mozilla Firefox (cela affecte toutes les versions de bureau Windows que j'ai essayées). Avec Google Chrome, Opera ou même Firefox mobile, les correspondances d'expression régulière prennent à peu près la même chose, travailleur ou non.

Si vous avez besoin de résoudre ce problème, assurez-vous de voter sur le rapport de bogue sur bugzilla . J'essaierai d'ajouter des informations supplémentaires si quelque chose change.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.