Pourquoi remplacer \s*
(ou même \s\s*
) avec \s+
entraîne une accélération de cette entrée?
use Benchmark qw(:all);
$x=(" " x 100000) . "_\n";
$count = 100;
timethese($count, {
'/\s\s*\n/' => sub { $x =~ /\s\s*\n/ },
'/\s+\n/' => sub { $x =~ /\s+\n/ },
});
J'ai remarqué une lente regex s/\s*\n\s*/\n/g
dans mon code - lors d'une 450KB fichier d'entrée composé de beaucoup d'espaces avec un peu de non-lieux, ici et là, et un dernier saut de ligne à la fin de la regex hung et jamais fini.
Je intuitivement a remplacé la regex avec s/\s+\n/\n/g; s/\n\s+/\n/g;
et tout allait bien.
Mais pourquoi est-il si rapide? Après l'utilisation de re Debug => "EXECUTE"
j'ai remarqué l' \s+
version est en quelque sorte optimisé pour exécuter en une seule itération: http://pastebin.com/0Ug6xPiQ
Matching REx "\s*\n" against " _%n"
Matching stclass ANYOF{i}[\x09\x0a\x0c\x0d ][{non-utf8-latin1-all}{unicode_all}] against " _%n" (9 bytes)
0 <> < _%n> | 1:STAR(3)
SPACE can match 7 times out of 2147483647...
failed...
1 < > < _%n> | 1:STAR(3)
SPACE can match 6 times out of 2147483647...
failed...
2 < > < _%n> | 1:STAR(3)
SPACE can match 5 times out of 2147483647...
failed...
3 < > < _%n> | 1:STAR(3)
SPACE can match 4 times out of 2147483647...
failed...
4 < > < _%n> | 1:STAR(3)
SPACE can match 3 times out of 2147483647...
failed...
5 < > < _%n> | 1:STAR(3)
SPACE can match 2 times out of 2147483647...
failed...
6 < > < _%n> | 1:STAR(3)
SPACE can match 1 times out of 2147483647...
failed...
8 < _> <%n> | 1:STAR(3)
SPACE can match 1 times out of 2147483647...
8 < _> <%n> | 3: EXACT <\n>(5)
9 < _%n> <> | 5: END(0)
Match successful!
Matching REx "\s+\n" against " _%n"
Matching stclass SPACE against " _" (8 bytes)
0 <> < _%n> | 1:PLUS(3)
SPACE can match 7 times out of 2147483647...
failed...
Je sais Perl 5.10+ sera immédiatement échouer la regex (sans courir) si un saut de ligne n'est pas présente. Je soupçonne que c'est à l'aide de l'emplacement de la nouvelle ligne de réduire la quantité de la recherche qu'il fait. Pour tous les cas ci-dessus, il semble habilement réduire la mandature impliqués (habituellement /\s*\n/
contre une chaîne d'espaces prendre exponentielle en temps). Quelqu'un peut-il offrir un aperçu de pourquoi l' \s+
version est beaucoup plus rapide?
Notez aussi que l' \s*?
n'offre aucune accélération.