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. P>
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]. P>
Les résultats me confondent beaucoup. Quelqu'un pourrait-il avoir un indice de la raison? P>
3 Réponses :
Il doit être plus lent. P>
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. p>
Cela provoque un petit retard mais avec de grandes boucles, il y aura une différence de temps p>
Dans le 1er exemple, il est déjà défini et évalué. p>
Par conséquent, la seule fois nécessaire à l'exécution. P>
jsperf.com montre 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 strong> OPS / S est plus rapide que 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). P>
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);
}
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>
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 () code>, 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.