【发布时间】:2021-02-19 12:40:17
【问题描述】:
我的程序运行缓慢,并且正在尝试提高性能。脚本“使用”模块中的一个子程序,并将一个非常大的数组传递给子程序。经过一番修改,我意识到如果我将子直接移动到父脚本中,并使数组全局而不是本地(所以我不必传递它),脚本会大大加快(在几分钟内运行它正在占用天)。
我真的很希望能够在模块中包含那个子(因为我有很多脚本调用同一个子)。但我也希望它快点。 :-)
半伪代码
page.pl:
package Page;
use Star;
my @fileBytes=();
open(StarFile, "<$File");
binmode(StarFile);
while (read(StarFile, $FileValues, 1)) {
push @fileBytes, $FileValues;
}
close(StarFile);
&parseBlock(\@fileBytes);
模块.pl:
package Star;
sub parseBlock {
my ($fileBytes) = @_;
my @fileBytes = @{ $fileBytes };
...
}
这里有一些阅读:https://www.perlmonks.org/?node=Variable%20Scoping%20in%20Perl%3A%20the%20basics 告诉我我想处理范围界定。所以如果我用“我们的”而不是“我的”来定义@fileBytes,它就会变成一个包值。据我所知,这通常在模块文件中。但我从父级中的值开始。
所以我可以让父级也成为一个包,定义: 我们的@fileBytes
然后从模块中引用它,至少类似于: @Page::fileBytes
我认为我至少在理论上是正确的。
当我想从不同的脚本中使用 sub 时,我的问题出现了:
其他.pl:
package Other;
use Star;
my @fileBytes=();
open(StarFile, "<$File");
binmode(StarFile);
while (read(StarFile, $FileValues, 1)) {
push @fileBytes, $FileValues;
}
close(StarFile);
&parseBlock(\@fileBytes, $offset);
现在我传递的值是 @Other::fileBytes 。这个问题随着我使用我的图书馆的次数越多而扩大。
我想做的是在模块中有子例程,但不必传递(我相信这是创建一个新值,这一定很慢)@fileBytes 数据,因为它是“全局的” , 这样我就可以使用集中式子了。
【问题讨论】:
-
这与范围无关。您将数组引用传递给
parseBlock(),这很好,因为它允许子例程直接访问此数据。在您的 subs 第二行中,您复制了可能不必要的数组内容,并且在大量数据不幸的情况下,但不太可能考虑您描述的性能差异(分钟与天)。见perlreftut -
一个简单而合理的做法是不在 sub 中创建一个本地数组
my @fileBytes = @{ $fileBytes };--- 而是使用$fileBytesarrayref(除非该数组在潜艇中得到改变!)。当然,如果数组很大,则该数据复制需要时间。不过,我仍然不明白这是如何将几分钟变成几天的,除非 sub 被多次调用...... -
我建议不要修改
our...您需要一个获取所需数据的子程序。如果数据大小存在合理问题,那么您需要重新考虑方法,而不是开始将事情全局化。
标签: arrays perl module subroutine