Почему регулярное выражение, предварительно скомпилированное с qr, медленнее, чем постоянное регулярное выражение?

Я только что увидел этот вопрос об оптимизации определенного регулярного выражения в Perl. Мне было интересно, сколько соответствий может выполнить моя машина, и я попробовал следующий простой тест:

  • case 1 - использование регулярного выражения, предварительно скомпилированного с qr
  • case 2 - обычный /regex/ match
use 5.014;
use warnings;

use Benchmark qw(:all);

my $str = "SDZ";
my $qr = qr/S?T?K?P?W?H?R?A?O?\*?E?U?F?R?P?B?L?G?T?S?D?Z?/;

say "match [$&]" if( $str =~ $qr );

my $res = timethese(-10, {
    stdrx => sub { $str =~ /S?T?K?P?W?H?R?A?O?\*?E?U?F?R?P?B?L?G?T?S?D?Z?/ },
    qr_rx => sub { $str =~ $qr },
});

cmpthese $res;

К моему удивлению, это дало следующий результат:

 match [SDZ]
Benchmark: running qr_rx, stdrx for at least 10 CPU seconds...
     qr_rx: 10 wallclock secs ( 9.99 usr +  0.01 sys = 10.00 CPU) @ 1089794.90/s (n=10897949)
     stdrx: 11 wallclock secs (10.58 usr +  0.04 sys = 10.62 CPU) @ 1651340.11/s (n=17537232)
           Rate qr_rx stdrx
qr_rx 1089795/s    --  -34%
stdrx 1651340/s   52%    --

то есть. обычный $str =~ /regex/ примерно на 50% быстрее, чем при использовании $str =~ qr

Я что-то не так делаю? Почему я получаю этот результат?

EDIT:

Просто скачал цитируемую книгу, мне есть чему поучиться :). Но цитируемая книга также говорит:

Если у литерала регулярного выражения нет интерполяции переменных, Perl знает, что регулярное выражение не может измениться от использования к использованию, поэтому после того, как регулярное выражение скомпилировано один раз, эта скомпилированная форма сохраняется («кэшируется») для использования всякий раз, когда выполнение снова достигает того же кода , Регулярное выражение проверяется и компилируется только один раз, независимо от того, как часто оно используется во время выполнения программы.

Итак, в приведенном выше примере оба регулярных выражения являются литеральными без интерполяции переменных. Таким образом, «скомпилированное» регулярное выражение должно быть таким же быстрым, как простое . В этом примере он медленнее на 50%.

Икегами объяснил, почему $str =~ $qr медленнее. (и, честно говоря, «медленнее» - это неправильный термин, потому что мы говорим о нескольких микросекундах ... :))

НО Perl Docs говорит:

  

Предварительная компиляция шаблона во внутреннее представление в   момент qr () избавляет от необходимости каждый раз перекомпилировать шаблон   попытка совпадения /$ pat /.

С точки зрения обычного пользователя perl («не какой-то высокоуровневый монах perl») это означает: предварительно скомпилируйте ваш шаблон - это будет быстрее , но на самом деле - это помогает только если регулярное выражение содержит некоторые "нестатические" части ...

Честно говоря, я до сих пор не понял этого полностью - но получил книгу и собираюсь учиться. :) Может быть, еще одно предложение в документации - может помочь новичкам не понять qr, когда они начинают учиться.

Спасибо всем!

4 голоса | спросил cajwine 25 MaramSat, 25 Mar 2017 01:08:02 +03002017-03-25T01:08:02+03:0001 2017, 01:08:02

1 ответ


0

Шаблоны регулярных выражений компилируются во время компиляции, если они не интерполируются. Ни регулярное выражение в операторе qr//, ни оператор в совпадении в stdrx интерполировать, поэтому оба компилируются во время компиляции.

Дополнительные 30 мкс, потраченные в тесте qr_rx, тратятся на «компиляцию» третьего регулярного выражения: в операторе сопоставления в qr_rx. Не забывайте, что $_ =~ $re - это сокращение от $_ =~ m/$re/. Теперь на самом деле компиляция не происходит, когда весь шаблон состоит из интерполированного предварительно скомпилированного регулярного выражения, потому что этот случай обрабатывается специально, но, очевидно, все еще требуется некоторое время, чтобы уговорить операцию совпадения использовать предварительно скомпилированное регулярное выражение. (Может быть, это нужно клонировать?)

ответил ikegami 25 MaramSat, 25 Mar 2017 08:10:58 +03002017-03-25T08:10:58+03:0008 2017, 08:10:58

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132