Perl v5.28.1
Тест:
use common::sense;
use Benchmark qw(:all);
my $UPPER = 10_000_000;
my $str = 'foo bar baz';
cmpthese(10, {
'empty for-loop' => sub {
for my $i (1..$UPPER) {}
},
'regex match' => sub {
for my $i (1..$UPPER) {
$str =~ /foo/;
}
},
'regex match (single compile)' => sub {
my $re = qr/foo/;
for my $i (1..$UPPER) {
$str =~ $re;
}
},
'regex match (anchor)' => sub {
for my $i (1..$UPPER) {
$str =~ /^foo/;
}
},
'regex match (anchor) (single compile)' => sub {
my $re = qr/^foo/;
for my $i (1..$UPPER) {
$str =~ $re;
}
},
});
Результаты:
s/iter regex match (anchor) (single compile) regex match (single compile) regex match (anchor) regex match empty for-loop
regex match (anchor) (single compile) 3.83 -- -21% -60% -84% -97%
regex match (single compile) 3.04 26% -- -50% -80% -96%
regex match (anchor) 1.53 151% 99% -- -61% -92%
regex match 0.601 537% 405% 154% -- -81%
empty for-loop 0.117 3170% 2496% 1205% 414% --
Поскольку foo происходит в начале строки, я ожидаю, что добавление явного якоря (^) к регулярному выражению ничего не сделает ... не уменьшит производительность вдвое!
Кроме того, я читал кое-что о том, что Perl достаточно умен, чтобы не перекомпилировал выражения с фиксированными строками, даже если они содержатся внутри циклов.
Но почему попытка вручную / явно «прекомпилировать» выражение в переменную $ re может привести к такому падению производительности ?!
Я изменил подстроку поиска "foo" на "asdf" (чего не происходит в $ str), и привязка позволяет движку быстрее прекращать поиск.
Но назначение выражения в переменную все еще является огромным ударом по производительности - гораздо больше, чем я ожидал! :
Rate regex match (single compile) regex match (anchor) (single compile) regex match regex match (anchor) empty for-loop
regex match (single compile) 0.401/s -- -10% -79% -83% -96%
regex match (anchor) (single compile) 0.447/s 11% -- -76% -81% -95%
regex match 1.88/s 369% 321% -- -19% -79%
regex match (anchor) 2.33/s 481% 421% 24% -- -75%
empty for-loop 9.17/s 2185% 1951% 387% 294% --
Итак, 2 вопроса для подведения итогов:
- Почему производительность якоря в начале строки должна быть в два раза меньше?
- Почему компиляция выражения (qr //) в переменную должна быть на 80% медленнее, чем при использовании одного и того же выражения в строке?