URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 5858
[ Назад ]

Исходное сообщение
"Почему m// быстрее чем m//o"

Отправлено alexvs , 29-Окт-06 22:48 
Везде пишется, что при многократном использовании одного регулярного шаблона лучше его предварительно скомпилировать, что даст прирост в производительности, но 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%       --

Я в недоумении, может кто-то объяснить причины такого результата?


Содержание

Сообщения в этом обсуждении
"Почему m// быстрее чем m//o"
Отправлено robot , 30-Окт-06 12:05 
Потому что ты сделал так, что получил обратное поведение.

$str=~/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/

вот этот регексп оптимизатор компилирует заранее и больше не трогает, потому что в нём все данные - статические. он быстрее

а вот в этот
$str=~/$patt/

ты засунул переменную. откуда оптимизатор знать, меняется она или нет? Он вынужден каждый цикл перекомпилировать регулярное выражение.

Где у тебя ключ /o который ты указал в теме сообщения?
qr - это не предкомипиляция.

perldoc perlre


"Почему m// быстрее чем m//o"
Отправлено alexvs , 30-Окт-06 12:23 
>Потому что ты сделал так, что получил обратное поведение.
>
>$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
________________________________________________________________________________________


"Почему m// быстрее чем m//o"
Отправлено robot , 30-Окт-06 12:38 
Я бы всё же посоветовал пользоваться не гуглом, а документацией perl

      qr/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,а не выискивать всякую ересь в гуглах :)


"Почему m// быстрее чем m//o"
Отправлено alexvs , 04-Ноя-06 17:18 
Большое спасибо, что избавили от неправильного понимания.