Неожиданное поведение скорости при тестировании регулярных выражений Perl - PullRequest
2 голосов
/ 08 октября 2010

Обсуждая относительные преимущества использования index() в Perl для поиска подстрок, я решил написать микро-тест, чтобы доказать, что я видел раньше, чем индекс быстрее, чем регулярные выражения при поиске подстроки.Вот код тестирования:

use strict;
use warnings;
use Benchmark qw(:all);

my @random_data;
for (1..100000) {
  push(@random_data, int(rand(1000)));
}

my $warn_about_counts = 0;
my $count = 100;
my $search = '99';

cmpthese($count, {
  'Using regex' => sub {
    my $instances = 0;
    my $regex = qr/$search/;
    foreach my $i (@random_data) {
      $instances++ if $i =~ $regex;
    }
    warn $instances if $warn_about_counts;
    return;
  },
  'Uncompiled regex with scalar' => sub {
    my $instances = 0;
    foreach my $i (@random_data) {
      $instances++ if $i =~ /$search/;
    }
    warn $instances if $warn_about_counts;
    return;
  },
  'Uncompiled regex with literal' => sub {
    my $instances = 0;
    foreach my $i (@random_data) {
      $instances++ if $i =~ /99/;
    }
    warn $instances if $warn_about_counts;
    return;
  },
  'Using index' => sub {
    my $instances = 0;
    foreach my $i (@random_data) {
      $instances++ if index($i, $search) > -1;
    }
    warn $instances if $warn_about_counts;
    return;
  },
});

Что меня удивило, так это то, как они работали (используя Perl 5.10.0 на последнем MacBook Pro).В порядке убывания скорости:

  1. Некомпилированное регулярное выражение с литералом (69,0 операций / сек)
  2. Использование индекса (61,0 операций / сек)
  3. Некомпилированное регулярное выражение со скаляром (56,8 операций в секунду)
  4. Использование регулярных выражений (17,0 операций в секунду)

Может ли кто-нибудь объяснить, что использует Perl voodoo для получения скорости двух несобственных регулярных выраженийвыполнить так же, как индексную операцию?Является ли это проблемой в данных, которые я использовал для генерации эталонного теста (в поисках вхождения 99 в 100 000 случайных целых чисел), или Perl способен выполнить оптимизацию во время выполнения?

Ответы [ 3 ]

2 голосов
/ 08 октября 2010

Оптовая версия

В свете комментария @ Ven'Tatsu я немного изменил тест:

use strict; use warnings;
use Benchmark qw(cmpthese);

use Data::Random qw( rand_words );
use Data::Random::WordList;

my $wl = Data::Random::WordList->new;

my @data_1 = (rand_words( size => 10000 )) x 10;
my @data_2 = @data_1;

my $pat = 'a(?=b)';
my $re = qr/^$pat/;

cmpthese(1, {
    'qr/$search/' => sub {
        my $instances = grep /$re/, @data_1;
        return;
    },
    'm/$search/' => sub {
        my $search = 'a(?=b)';
        my $instances = grep /^$search/, @data_2;
        return;
    },
});

В Windows XP с ActiveState perl 5.10.1:

              Rate qr/$search/  m/$search/
qr/$search/ 5.40/s          --        -73%
m/$search/  20.1/s        272%          --

В Windows XP с Strawberry perl 5.12.1:

              Rate qr/$search/  m/$search/
qr/$search/ 6.42/s          --        -66%
m/$search/  18.6/s        190%          --

В ArchLinux с bleadperl:

              Rate qr/$search/  m/$search/
qr/$search/ 9.25/s          --        -38%
m/$search/  14.8/s         60%          --
2 голосов
/ 08 октября 2010

Ну, ваш случай "Использование регулярных выражений" настолько медленный, потому что вы каждый раз его компилируете. Попробуйте вытащить его из подпрограммы.

1 голос
/ 08 октября 2010

Perl оптимизирует многие вещи. Ваш шаблон без специальных функций регулярных выражений и буквенных символов позволяет движку регулярных выражений Perl упростить многие вещи Использование use re 'debug' может показать вам, что на самом деле происходит за кулисами.

...