Perl 锚定的正则表达式性能

互联网 行业动态 更新时间:2024-06-13 00:19:32

cho*_*oba 6

您不太可能优化正则表达式引擎。但是,如果性能是您的目标,您可以专注于代码的其他部分。例如,试试这个:

for my $bad_pattern (@bad_patterns) {
    my $re = qr/^\Q$bad_pattern\E/;
    delete @$hash{ grep /$re/, sort keys %$hash };
}

在我的机器上,它运行得更快(无论是否存在锚点),因为 grep 的表达式形式不必创建范围,并且正则表达式的复杂编译对于每个错误模式只发生一次。

zdi*_*dim 5

这是一个相当简单的匹配,模式是一个固定的字符串。因此,锚定模式通常必须更快。分析证实了这一点,96 ns/call vs 107 ns/call。

但是当我对锚定和非锚定版本的代码进行基准测试时,它们并驾齐驱。这是关于代码的其余部分,它压倒了正则表达式的匹配:sort不需要比较键,并且正则表达式正在grep's 循环内编译,不需要。

当这得到缓解时,我确实让锚定呼叫快了 11--15%(多次运行)

use warnings;
use strict;
use feature 'say';

use Data::Dump;
use Storable qw(dclone);
use Benchmark qw(cmpthese);

my $runfor = shift // 3;

my @states = qw(KansasCity MississippiState ColoradoMountain IdahoInTheNorthWest AnchorageIsEvenFurtherNorth);
my @cities = qw(WitchitaHouston ChicagoDenver);
my @streets = qw(DowntownMainStreetInTheCity CenterStreetOverTheHill HickoryBasketOnTheWall);
my @seasoncode = qw(8000S 8000P 8000F 8000W);
my @historycode = qw(7000S 7000P 7000F 7000W 7000A 7000D 7000G 7000H);
my @sides = qw(left right up down);

my @bad_patterns = ( 
    'KansasCity[0].WitchitaHouston[1].DowntownMainStreetInTheCity[2]',
    'ColoradoMountain[0].ChicagoDenver[1].HickoryBasketOnTheWall[2].8000F'
);

my $hash_1;
for my $state (@states) {
    for my $city (@cities) {
        for my $street (@streets) {
            for my $season (@seasoncode) {
                for my $history (@historycode) {
                    for my $side (@sides) {
                        $hash_1->{$state . '[0].' . $city . '[1].' . $street . '[2].' . $season . '.' . $history . '.' . $side} = 1;
                    }
                }
            }
        }
    }   
}    
my $hash_2 = dclone $hash_1;

#say for @bad_patterns; say '---'; dd $hash_1; exit;

sub no_anchor {
    for my $bad_pattern (@bad_patterns) {
        my $re = qr/\Q$bad_pattern\E/;
        delete @$hash_2{ grep { /$re/ } keys %$hash_2 };
    }   
}   
sub w_anchor {
    for my $bad_pattern (@bad_patterns) {
        my $re = qr/^\Q$bad_pattern\E/;
        delete @$hash_1{ grep { /$re/ } keys %$hash_1 };
    }
}


cmpthese( -$runfor, {
    'no_anchor' => sub { no_anchor() },
    'w_anchor'  => sub { w_anchor() },
});

我让比较潜艇使用外部数据(通常不传递给经过测试的潜艇),以减少任何额外的工作,然后我使用使用Storable::dclone.

上述基准测试的输出运行了 10 秒(运行10时传递给程序):

           Rate no_anchor  w_anchor
no_anchor 296/s        --      -13%
w_anchor  341/s       15%        --

因此,锚定版本确实赢了,尽管幅度不大。有了这些数据,匹配在大约 96% 的情况下会失败,尽管如此,非锚定版本的工作量更大,必须搜索整个字符串;我预计会有更大的差异。

运行时的相对接近是由于其余的代码(grep,哈希操作,循环),特别是正则表达式编译成本,被包含在时间中,这稀释了匹配效率本身的差异。

这为我们提供了关于时序代码的重要一课:它可能很微妙。需要确保仅比较相关部分,并且公平(在平等情况下)。

更多推荐

性能,正则表达式,Perl

本文发布于:2023-04-21 09:49:24,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/hyzx/d60a6fd5d9e83be07ada310ecc2e6eda.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:性能   正则表达式   Perl

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!