Perl 可以在我的 Macbook 上在大约 100 毫秒内比较 10,000 个成对元素的列表,所以我要说的第一件事是分析你的代码以确保这确实是问题所在。
做一些基准测试,你可以做一些事情来加快速度。
假设您有很多不匹配的比较,这将节省大量时间。
如果它们的数组长度不同,则它们永远不会匹配。比较它们的尺寸,如果它们不同,请尽早返回。这避免了需要在循环内一遍又一遍地检查这种情况。
成对迭代你通常会做类似的事情,for( my $idx = 0; $idx <= $#a; $idx += 2 )
但迭代数组比使用 C 风格的 for 循环更快。这是 Perl 的一个优化技巧,在优化的 C 中在 perl 中执行工作比在 Perl 代码中执行更有效。这会为您带来大约 20%-30% 的收益,具体取决于您如何对其进行微优化。
for my $mark (0..$#{$a}/2) {
my $idx = $mark * 2;
next if !defined $a->[$idx] || !defined $b->[$idx];
return 0 if $a->[$idx] ne $b->[$idx] || $a->[$idx+1] ne $b->[$idx+1];
}
return 1;
由于一组对是固定的,您可以生成定义了哪些对的索引。这使得迭代器更加简单和快速。
state $indexes = precompute_indexes($b);
for my $idx ( @$indexes ) {
next if !defined $a->[$idx];
return 0 if $a->[$idx] ne $b->[$idx] || $a->[$idx+1] ne $b->[$idx+1];
}
return 1;
没有空值,这是 40% 的性能提升。你得到的越多,固定集中的空值就越多。
use strict;
use warnings;
use v5.10; # for state
# Compute the indexes of a list of pairs which are interesting for
# comparison: those with defined keys.
sub precompute_indexes {
my $pairs = shift;
die "Unbalanced pairs" if @$pairs % 2 != 0;
my @indexes;
for( my $idx = 0; $idx <= $#$pairs; $idx += 2 ) {
push @indexes, $idx if defined $pairs->[$idx];
}
return \@indexes;
}
sub cmp_pairs_ignore_null_keys {
my($a, $b) = @_;
# state is like my but it will only evaluate once ever.
# It acts like a cache which initializes the first time the
# program is run.
state $indexes = precompute_indexes($b);
# If they don't have the same # of elements, they can never match.
return 0 if @$a != @$b;
for my $idx ( @$indexes ) {
next if !defined $a->[$idx];
return 0 if $a->[$idx] ne $b->[$idx] || $a->[$idx+1] ne $b->[$idx+1];
}
return 1;
}
我仍然相信在 SQL 中使用自连接会更好,但还没有解决。