将较大的值传递给模块

问题描述

我的程序运行缓慢,并且试图提高性能。脚本“使用”模块中的一个子对象,然后将相当大的数组传递给该子对象。经过一番修补后,我意识到如果将子直接移到父脚本中,并使数组成为全局数组而不是局部数组(因此我不必传递它),则脚本的运行速度大大提高(运行时间仅需几分钟)天)。

我真的很希望能够在模块中包含该子对象(因为我有许多脚本调用了该子对象)。但我也希望它快。 :-)

半伪代码

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);

Module.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时出现我的问题:

other.pl:

package Other;
use Star;

  my @fileBytes=();
  open(StarFile,"<$File");
  binmode(StarFile);
  while (read(StarFile,1)) {
    push @fileBytes,$FileValues; 
  }
  close(StarFile);

&parseBlock(\@fileBytes,$offset);

现在我传递的值是@Other :: fileBytes。当我使用图书馆时,这个问题就扩大了。

我想做的是在模块中有子例程,但不必传递@fileBytes数据(我相信它正在创建一个新值,该值必须很慢),因为它是“全局”的,以使我可以使用集中式子控件。

解决方法

您不能将数组传递给sub,只能传递标量。当使用f(@a)时,将传递数组的元素。这不会创建任何新的标量或复制任何标量,因此实际上它的速度非常快。

但是,即使很小的成本也可以避免。这是通过将引用传递给数组f(\@a)来完成的。这确实创建了一个标量,但这是所有标量中最轻的。

这是您已经在做的,因此从调用子程序的角度来看,您已经拥有最快的速度。您面临的问题是在调用sub之后立即执行操作的结果:创建一个新数组并将所提供数组的每个元素复制到该新数组中。

my @fileBytes = @{ $fileBytes };  # Copies every element.

删除该行,您的问题已解决。当然,您需要将使用重复数组(@fileBytes)的所有代码更改为使用原始数组(@$fileBytes)。唯一的警告是,对数组的任何更改都将反映在通过引用传递给子对象的数组中,因为它是同一数组。


替代解决方案

如果您坚持要避免使用引用,则可以使用以下内容:

use experimental qw( declared_refs );

my \@fileBytes = $fileBytes;

有效地使@fileBytes成为@$fileBytes的别名。不涉及复制。它不是免费的,但也不便宜(O(1))。就像直接修改@$filesBytes一样,修改@fileBytes也会影响调用方中的数组。

通常来说,应该避免在生产中使用实验代码,但是开发人员计划在Perl的下一个主要版本中默认启用它,因此他们肯定认为它相当稳定。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...