我正在寻找一种方法来加快我的perl执行速度。我有一个脚本,读取一个文件并创建一个二维哈希(至少有800万个键值对)。然后我根据用户的输入创建了两个独立的哈希,其中包含了2D哈希的第一级和第二级键值。但是当我试图将这些数据组合起来打印出来时,执行速度非常慢。以下是打印数据的代码块(脚本中最耗时的部分)。
open(my $FH_DATA, ">", $report_graph) or die "Cannot open file $!";
print $FH_DATA "$HEADER_GRAPH\n";
foreach my $first_key ( keys %first_level_hash) {
foreach my $second_key (keys %second_level_hash ) {
foreach my $rail (@FILTER_BY_RAILS) {
if( exists $FILTER_BY_RAIL_COMMON{"$first_key.$second_key.$rail"} ) {
print $FH_DATA " $_ " for @{ $my_2D_hash{$first_key}{$second_key} };
print $FH_DATA "$rail $second_key $first_key";
print $FH_DATA "\n";
}
}
}
}
close($FH_DATA);
print "Finished writing $report_graph\n";
这个嵌套的foreach循环真的很耗费我的执行时间。我一直在不断地看它,现在成了瞎子。任何帮助都是非常感激的。
更新 由于问题中的一个关键细节已经更新,所以进行了重大改写。
这段代码去掉了两个嵌套的哈希键,为每个哈希键准备相同的东西。$rail
-过滤后的条目。这些涉及到解除引用的哈希查找并不是很自由,而且会增加。由于每个过滤循环中与打印相关的哈希部分都是一样的,所以在外面准备它们
foreach my $first_key ( keys %first_level_hash) {
foreach my $second_key (keys %second_level_hash ) {
my @line_elems = @{ $my_2D_hash{$first_key}{$second_key} };
foreach my $rail (
grep { exists $FILTER_BY_RAIL_COMMON{"$first_key.$second_key.$_"} }
@FILTER_BY_RAILS)
{
print $FH_DATA " $_ " for @line_elems;
print $FH_DATA "$rail $second_key $first_key";
print $FH_DATA "\n";
}
}
该 grep
的效率也应该比 if
语句的显式循环。
总的来说,这肯定会有帮助,但如果 @FILTER_BY_RAILS
是小的,那么可能就不会大幅。
这大约是在不能够重新安排操作的情况下可以做到的。一个重大的改进是在之前,也许是在哈希值被填充的时候进行过滤,这样就可以创建一个单独的数据结构,准备打印。 然后循环也可以更有效地解开一些)。
这还是要付出一些代价的,哈希值的速度并不快,而且在大的哈希值上迭代需要周期。
一个小的调整也可以尝试,因为可能更快的是在打印本身
print $FH_DATA ' '.join(' ', @$line).' ';