对Perl正则表达式进行基准测试时出现意外的速度行为

时间:2010-10-08 08:55:00

标签: regex perl benchmarking

在讨论在Perl中使用index()搜索子字符串的相对优点时,我决定编写一个微基准来证明我之前看到的内容,而索引在查找子字符串时比正则表达式更快。以下是基准测试代码:

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;
  },
});

我感到惊讶的是这些表现如何(在最近的MacBook Pro上使用Perl 5.10.0)。按速度降序排列:

  1. 带有文字的未编译正则表达式(69.0 ops / sec)
  2. 使用索引(61.0 ops / sec)
  3. 带有标量的未编译正则表达式(56.8 ops / sec)
  4. 使用正则表达式(17.0 ops / sec)
  5. 任何人都能解释一下,为了获得两个未处理的正则表达式的执行速度以及索引操作,Perl正在使用什么voodoo?这是我用来生成基准测试的数据中的一个问题(寻找100,000个随机整数中出现的99个)还是Perl能够进行运行时优化?

3 个答案:

答案 0 :(得分:2)

好吧,你的情况“使用正则表达式”是如此之慢,因为你每次都在编译它。尝试将其移出子程序。

答案 1 :(得分:2)

批发修订

根据@ 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%          --

在带有草莓的perl 5.12.1:

的Windows XP上
              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 :(得分:1)

Perl优化了很多东西。没有特殊正则表达式特征和文字字符的模式允许perl的正则表达式引擎简化许多事情。使用use re 'debug'可以向您显示幕后实际发生的情况。