Везде пишется, что при многократном использовании одного регулярного шаблона лучше его предварительно скомпилировать, что даст прирост в производительности, но benchmark даёт противоположный результат:
#!/usr/bin/perl
use Benchmark qw/cmpthese countit/;my $str = "1162161865.634 1082 192.168.1.2 TCP_MISS/200 387 GET http://www.opennet.me/cgi-bin/opennet/hints.cgi? - DIRECT/82
.137.161.90 text/html";sub run($) { countit(5,@_); }
cmpthese {
pattern1 => run q{
for(my $i=0;$i<10000;$i++)
{
my $ip = $1 if($str=~/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
}
},
pattern2 => run q{
my $patt=qr/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
for(my $i=0;$i<10000;$i++)
{
my $ip = $1 if($str=~/$patt/);
}
},
};
даёт стабильно такой результат:
Rate pattern2 pattern1
pattern2 53.4/s -- -23%
pattern1 69.5/s 30% --Я в недоумении, может кто-то объяснить причины такого результата?
Потому что ты сделал так, что получил обратное поведение.$str=~/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
вот этот регексп оптимизатор компилирует заранее и больше не трогает, потому что в нём все данные - статические. он быстрее
а вот в этот
$str=~/$patt/ты засунул переменную. откуда оптимизатор знать, меняется она или нет? Он вынужден каждый цикл перекомпилировать регулярное выражение.
Где у тебя ключ /o который ты указал в теме сообщения?
qr - это не предкомипиляция.perldoc perlre
>Потому что ты сделал так, что получил обратное поведение.
>
>$str=~/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
>
>вот этот регексп оптимизатор компилирует заранее и больше не трогает, потому что
>в нём все данные - статические. он быстрее
>
>а вот в этот
>$str=~/$patt/
>
>ты засунул переменную. откуда оптимизатор знать, меняется она или нет? Он вынужден
>каждый цикл перекомпилировать регулярное выражение.
>
>Где у тебя ключ /o который ты указал в теме сообщения?
>qr - это не предкомипиляция.
>
>perldoc perlre
Вы так уверено об этом говорили, что я чуть не поверил.. спас ГУГЛ:________________________________________________________________________________________
6.4.6.3. Создание регулярного выражения
Синтаксис: qr/string/modifiersЭта конструкция создает регулярное выражение с текстом string и модификаторами modifiers и компилирует его. Если ограничителями являются символы '', то интерполяция строки string не производится. В остальных случаях происходит интерполяция образца и если он содержит переменные, то при каждом сопоставлении производится его компиляция. Чтобы избежать этого, используйте модификатор o (разумеется, если вы уверены, что значения переменных, входящих в образец, остаются неизменными).
Однажды созданное регулярное выражение может употребляться как самостоятельно, так и в качестве фрагмента других регулярных выражений. Примеры:
$re = qr/\d+/;
$string =~ /\s*${re}\s*/; # включение в другое регулярное выражение
$string =~ $re; # самостоятельное использование
$string =~ /$re/; # то же самое$re = qr/$header/is;
s/$re/text/; # то же, что s/$header/text/is
________________________________________________________________________________________
Я бы всё же посоветовал пользоваться не гуглом, а документацией perlqr/STRING/imosx
This operator quotes (and possibly compiles) its STRING as a
regular expression. STRING is interpolated the same way as
PATTERN in "m/PATTERN/". If "'" is used as the delimiter, no
interpolation is done. Returns a Perl value which may be used
instead of the corresponding "/STRING/imosx" expression.Иначе говоря qr{STRING} = m/STRING/ оно принудительно НЕ компилирует регексп. Оно его скомпилирует если там не будет переменных. Принудительная компиляция - ключ /o.
В примере, который приведён в первом сообщении непосредственно сравнение вообще идет в другом месте - /$patt/. Это отдельное регулярное выражение, СОДЕРЖАЩЕЕ ПЕРЕМЕННУЮ. Оно будет компилироваться каждый раз, если не поставить ключ /o.
Если хочешь применить скомпилирванный регексп, почему бы не сделать просто $a =~ $b ?
Таки настоятельно рекомендую ознакомитья с документацией языка perl,а не выискивать всякую ересь в гуглах :)
Большое спасибо, что избавили от неправильного понимания.