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

标签 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 次操作/秒)
  2. 使用索引(61.0 次操作/秒)
  3. 未编译的标量正则表达式(56.8 次操作/秒)
  4. 使用正则表达式(17.0 次操作/秒)

谁能解释一下 voodoo Perl 使用什么来获得两个未编译的正则表达式以及索引操作的执行速度?这是我用来生成基准的数据中的问题(查找 100,000 个随机整数中 99 的出现次数)还是 Perl 能够进行运行时优化?

最佳答案

批发修订版

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

在带有 ActiveState perl 5.10.1 的 Windows XP 上:

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

在装有 Strawberry perl 5.12.1 的 Windows XP 上:

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

在带有 bleadperl 的 ArchLinux 上:

              Rate qr/$search/  m/$search/
qr/$search/ 9.25/s          --        -38%
m/$search/  14.8/s         60%          --

关于regex - 对 Perl 正则表达式进行基准测试时出现意外的速度行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3889036/

相关文章:

c++ - Windows 中优于 100ns 的分辨率计时器

java - 如何获取模式匹配后的子字符串?并从初始字符串中删除找到的子字符串

JavaScript 正则表达式从 HTML 样式标签中提取文本

perl - 在 perl 中将文件句柄作为参数发送

java - 测量生产环境中 Java Web 服务的方法执行时间

c++ - 在 C(也许是 C++)中寻找数值/多媒体/信号处理基准

regex - Shell脚本,替换下划线+空格+可能的数字

r - 将全角字符串转换为半角字符串

perl - 查找 perl 污点模式错误的根源

linux - perl 输出奇怪的 `pwd`