我测试的哈希包含大约70000所大学,每所大学包含大约20名学生。我尝试了5次,以下是结果。foreach性能和while(每个)性能存在很大差异。为什么呢?
带while循环的代码:
while ( my ($college_code, $college_info_hr) = each (%{$college_data_hr}) ) {
while ( my ($student_num, $student_info_hr) = each (%{$college_info_hr->{'students'}}) ) {
if($student_num < 104000) { ## Delete the info of students before 2004.
delete $college_info_hr->{'students'}{$student_num};
}
}
}
带foreach循环的代码:
foreach my $college_code (keys %{$college_data_hr}) {
foreach my $student_num (keys %{$college_data_hr->{$college_code}{'students'}}) {
if($student_num < 104000) { ## Delete the info of students before 2004.
delete $college_data_hr->{$college_code}{'students'}{$student_num};
}
}
}
当大学数量为70,000时,执行时间为:
对于while循环的代码(间隔时间以秒为单位):
间隔时间:2.186621
间隔时间:2.058644
间隔时间:2.055645
间隔时间:2.101637
间隔时间:2.124632
对于带有foreach循环的代码:(间隔时间以秒为单位)
间隔时间:1.341768
间隔时间:1.436751
间隔时间:1.346529
间隔时间:1.302775
间隔时间:1.356765
当大学数量是248,000时,执行时间是:
(while循环的执行时间)
间隔时间:9.084427
间隔时间:8.438684
间隔时间:9.329338
间隔时间:9.169687
(foreach循环的执行时间)
间隔时间:5.502048
间隔时间:6.386692
间隔时间:5.596032
间隔时间:5.620144
问题是Perl无法进行一些优化,这在许多编译的编程语言中都是很常见的。正如ikegami指出的那样,在每个循环中,您都从哈希中复制数据,并且您还会执行许多不必要的哈希查找。您可以使用一些基准代码。
#!/usr/bin/env perl
use 5.10.0;
use strict;
use warnings;
use Benchmark qw(:hireswallclock :all);
use Clone qw(clone);
my $data = {
map +( $_ => { students => { map +( $_ => undef ), 103991 .. 104010 } } ),
1 .. 70000
};
my $college_data_hr;
sub sum_time {
my $t = shift;
$t = timesum( $t, $_ ) for @_;
return $t;
}
sub my_cmp_these {
my %bench = @_;
my %times;
for ( 1 .. 10 ) {
push @{ $times{$_} }, do {
$college_data_hr = clone($data);
timeit( 1, $bench{$_} );
}
for keys %bench;
}
$_ = sum_time(@$_) for values %times;
cmpthese( \%times );
}
my_cmp_these(
orig_while => sub {
while ( my ( $college_code, $college_info_hr )
= each( %{$college_data_hr} ) )
{
while ( my ( $student_num, $student_info_hr )
= each( %{ $college_info_hr->{'students'} } ) )
{
if ( $student_num < 104000 )
{ ## Delete the info of students before 2004.
delete $college_info_hr->{'students'}{$student_num};
}
}
}
},
new_while => sub {
while ( my ( undef, $college_info_hr ) = each( %{$college_data_hr} ) )
{
my $s = $college_info_hr->{'students'};
while ( my ( $student_num, undef ) = each(%$s) ) {
if ( $student_num < 104000 )
{ ## Delete the info of students before 2004.
delete $s->{$student_num};
}
}
}
},
orig_foreach => sub {
foreach my $college_code ( keys %$college_data_hr ) {
foreach my $student_num (
keys %{ $college_data_hr->{$college_code}{'students'} } )
{
if ( $student_num < 104000 )
{ ## Delete the info of students before 2004.
delete $college_data_hr->{$college_code}{'students'}
{$student_num};
}
}
}
},
new_foreach => sub {
foreach my $college_info ( values %$college_data_hr ) {
my $students = $college_info->{'students'};
delete @$students{ grep $_ < 104000, keys %$students };
}
},
ikegami_foreach => sub {
for my $college_code ( keys %$college_data_hr ) {
my $students = $college_data_hr->{$college_code}{students};
delete @$students{ grep $_ < 104000, keys %$students };
}
},
);
我的笔记本上的结果:
s/iter orig_while new_while orig_foreach ikegami_foreach new_foreach
orig_while 1.56 -- -25% -31% -35% -40%
new_while 1.17 33% -- -8% -14% -21%
orig_foreach 1.08 44% 8% -- -6% -14%
ikegami_foreach 1.01 54% 16% 7% -- -8%
new_foreach 0.927 68% 26% 16% 9% --
的结果 248,000
s/iter orig_while new_while orig_foreach ikegami_foreach new_foreach
orig_while 6.19 -- -27% -30% -33% -38%
new_while 4.54 36% -- -5% -8% -16%
orig_foreach 4.31 44% 5% -- -4% -11%
ikegami_foreach 4.16 49% 9% 4% -- -8%
new_foreach 3.83 62% 19% 13% 9% --
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句