Почему замена \s*
(или даже \s\s*
) на \s+
приводит к такому ускорению для этого ввода?
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/ },
});
Я заметил медленное регулярное выражение s/\s*\n\s*/\n/g
в моем коде - при заданном входном файле 450 КБ, состоящем из множества пробелов с несколькими не-пробелами здесь и там, и окончательной новой строки в конце - регулярное выражение зависало и никогда не заканчивалось.
Я интуитивно заменил регулярное выражение на s/\s+\n/\n/g; s/\n\s+/\n/g;
, и все было хорошо.
Но почему это намного быстрее? После использования re Debug => "EXECUTE"
я заметил, что версия \s+
оптимизирована для работы только в одной итерации: 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...
Я знаю, что Perl 5.10+ будет немедленно вызывать регулярное выражение (без его запуска), если новая строка отсутствует. Я подозреваю, что он использует расположение новой строки для уменьшения объема поиска. Для всех вышеперечисленных случаев он, кажется, умело уменьшает задействованный backtracking (обычно /\s*\n/
против строки пространств занимает экспоненциальное время). Может ли кто-нибудь дать понять, почему версия \s+
намного быстрее?
Также обратите внимание, что \s*?
не предлагает ускорения.