【发布时间】:2021-12-20 07:28:58
【问题描述】:
问题和数据
这篇文章的底部是生成此 NYTProf 数据的整个脚本。该脚本构建一个哈希,然后尝试删除包含某些错误模式的键。通过 NYTProf 运行代码会生成以下内容
delete @$hash{ grep { /\Q$bad_pattern\E/ } sort keys %$hash };
# spent 7.29ms making 2 calls to main::CORE:sort, avg 3.64ms/call
# spent 808µs making 7552 calls to main::CORE:match, avg 107ns/call
# spent 806µs making 7552 calls to main::CORE:regcomp, avg 107ns/call
对 main::CORE:match 和 main::CORE:regcomp 的调用超过 7,000 次。假设这是足以降低噪音水平的调用量。
继续!仅当不良模式出现在键的开头时才需要删除它们。听起来很棒!添加 ^ 来锚定正则表达式应该可以提高性能。但是,NYTProf 会生成以下内容。 NYTprof 已经运行了很多次了,还是比较一致的
delete @$hash{ grep { /^\Q$bad_pattern\E/ } sort keys %$hash };
# spent 7.34ms making 2 calls to main::CORE:sort, avg 3.67ms/call
# spent 1.62ms making 7552 calls to main::CORE:regcomp, avg 214ns/call
# spent 723µs making 7552 calls to main::CORE:match, avg 96ns/call
问题
锚定正则表达式几乎使这些 main::CORE:* 方法所花费的时间增加了一倍。但是锚定的正则表达式应该可以提高性能。这个数据集有什么独特之处导致锚定的正则表达式花费这么多额外的时间?
整个脚本
use strict;
use Devel::NYTProf;
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 $hash;
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->{$state . '[0].' . $city . '[1].' . $street . '[2].' . $season . '.' . $history . '.' . $side} = 1;
}
}
}
}
}
}
sub CleanseHash {
my @bad_patterns = (
'KansasCity[0].WitchitaHouston[1].DowntownMainStreetInTheCity[2]',
'ColoradoMountain[0].ChicagoDenver[1].HickoryBasketOnTheWall[2].8000F'
);
for my $bad_pattern (@bad_patterns) {
delete @$hash{ grep { /^\Q$bad_pattern\E/ } sort keys %$hash };
}
}
DB::enable_profile();
CleanseHash();
DB::finish_profile();
【问题讨论】:
-
sort和match更快,更慢的是regcomp- 这是正则表达式的编译。 -
也许你误解了你的任务。如果您只需要删除
@bad_patterns中包含的哈希键,则根本不需要正则表达式。delete @$hash{ @bad_patterns } -
还要检查较大的固定字符串中是否存在固定子字符串,您应该使用
index()。
标签: regex performance perl profiling