0
votes

Pourquoi JavaScript Regex regex exécution littéral est-il plus lent lorsqu'il est attribué à une variable?

Ma question est liée à une précédente Stackoverflow Post , qui dit les deux manières suivantes ont presque la même vitesse.

Mais lorsque je le teste en réalité en utilisant la boucle Nombre 1000000, il semble y avoir une performance constante. Bien que j'attends, l'exemple 1 devrait être plus rapide, mais il s'avère plus lent que l'exemple 2.

Les résultats de la page de test sont ici . Par exemple, les temps d'exécution sont les suivants: [20.27,19.82, 16.17], mais par exemple 2, ils sont moins: [18.57, 15.48, 15.14].

Les résultats me confondent beaucoup. Quelqu'un pourrait-il avoir un indice de la raison? xxx


2 commentaires

Comment tu timing ça? Je pense que pour que le point de repère soit significatif, il ne faut que mesurer uniquement les appels vers EXEC () , et non rien d'autre (rien d'autre "ne pas être pertinent pour la performance de la regex).


lien que vous avez fourni pour effectuer les tests mesures des opérations / SEC et non du temps écoulé. Lorsque j'ai exécuté les tests, j'ai constaté que l'ops / s est davantage par exemple 1 que l'exemple 2, ce qui signifie que la méthode de l'exemple 1 est effectivement plus rapide que la méthode de l'exemple 2.


3 Réponses :


0
votes

Il doit être plus lent.

Parce que chaque fois que vous allez dans une nouvelle itération dans la boucle, vous réévaluez la regex avant de l'exécuter.

Cela provoque un petit retard mais avec de grandes boucles, il y aura une différence de temps

Dans le 1er exemple, il est déjà défini et évalué.

Par conséquent, la seule fois nécessaire à l'exécution.


0 commentaires

0
votes

jsperf.com montre ops / sec , pas de temps d'exécution, pas d'exécution . Ainsi, plus la valeur est élevée, plus le code est rapide.

La première version est plus rapide, pas plus lente. Vous avez des résultats déroutants en exécutant un nombre différent d'itérations dans un ensemble de tests. 20,27 OPS / S est plus rapide que 18.57 OPS / s.

Il n'y a pas de question - la mise en cache de la réégycle dans une variable séparée va être plus rapide que la compilation dans chaque itération (les caches V8 VM compilèrent Regex mais apparemment pas aussi efficacement que le fait explicitement).


0 commentaires

0
votes

Ceci est un test étendu de la question originale (avec les temps de l'une de mes pistes, c'est la première fois pour "Hello World!", la seconde avec "A")

let str = "Hello World!"; // Alternative "a" 

// Literal in loop         (392 ms, 384 ms)
for (let i = 0; i < 10000; ++i) {
    for(let j = 0; j < 1000; ++j)
        /[aeiou]+/gi.exec(str);
}

// Construction in loop    (1747 ms, 1677 ms)
for (let i = 0; i < 10000; ++i) {
    for(let j = 0; j < 1000; ++j)
        new RegExp("[aeiou]+", "gi").exec(str);
}

// Cached literal          (335 ms, 252 ms, fastest)
for (let i = 0; i < 10000; ++i) {
    let regex = /[aeiou]+/gi;
    for(let j = 0; j < 1000; ++j)
        regex.exec(str);
}

// Cached construction     (351 ms, 270 ms)
for (let i = 0; i < 10000; ++i) {
    let regex = new RegExp("[aeiou]+", "gi");
    for(let j = 0; j < 1000; ++j)
        regex.exec(str);
}
  • Le littéral est toujours plus rapide que la version du constructeur: Li>
  • La version mise en cache est toujours plus rapide que la version inline li>
  • La différence entre le littéral à l'intérieur de la boucle et le littéral à l'extérieur de la boucle est petite par rapport à la construction à l'intérieur de la boucle li>
  • Les frais généraux du littéral dans la boucle sont si petits que cela ne concerne que de nombreuses itérations sur des chaînes courtes (lisibilité contre les performances d'exécution dans des cas plus complexes) li> ul>

    Cette observation pourrait être partiellement expliquée par le paragraphe suivant de La référence MDN RegexP : P>

    La notation littérale fournit une compilation de l'expression régulière lorsque l'expression est évaluée. Utilisez la notation littérale lorsque l'expression régulière restera constante. Par exemple, si vous utilisez la notation littérale pour construire une expression régulière utilisée dans une boucle, l'expression régulière ne sera pas recompilée sur chaque itération. P> blockQquote>

    Il semble que, même si tous les littéraux sont compilés pendant le chargement, il est encore nécessaire de construire un objet Regexp du littéral compilé qui provoque la surcharge du littéral dans la boucle qui est petite par rapport à la compilation d'exécution avec la constructeur dans la boucle p> p>


0 commentaires