在perl中为数组预分配内存有什么用?

时间:2016-04-21 16:49:31

标签: arrays perl

Perl允许预先分配的数组。我们可以在使用前预先分配数组,然后我们可以添加更多元素。例如,分配50个阵列成员然后添加第51个成员,因为阵列是可扩展的。那么预分配数组会提高性能吗?

1 个答案:

答案 0 :(得分:13)

这是因为计算机中的内存分配方式。计算机存储器就像白板上的空间:它具有与其他存储器相关的位置;它不能移动,必须复制。

如果您创建一个小数组,它可能如下所示:

@array = (1, 4, 8, 12, 19);

allocate memory for @array
______________________|               |______| a b c|__________

copy in the data
______________________|  1  4  8 12 19|______| a b c|__________

_是未分配的内存。 |表示分配给数组的范围。 | a b c|是其他一些数组。

然后,如果你多次推入该阵列,Perl将不得不重新分配内存。在这种情况下,它可以将已经存在的内存增加到未分配的空间中。

push @array, 23, 42;

grow the existing memory
______________________|  1  4  8 12 19      | a b c|__________

add the new data
______________________|  1  4  8 12 19 23 42| a b c|__________

如果你将更多数字推到@array,会发生什么?它不能再增长你的记忆了,还有另一个阵列。所以,就像在白板上一样,它必须将整个阵列复制到一大块内存中。

push @array, 85, 99;

Allocate a new chunk of memory
|                           |  1  4  8 12 19 23 42| a b c|__________

Copy the existing data
|  1  4  8 12 19 23 42      |  1  4  8 12 19 23 42| a b c|__________

Deallocate the old memory
|  1  4  8 12 19 23 42      |__1__4__8_12_19_23_42| a b c|__________

Add the new data
|  1  4  8 12 19 23 42 85 99|__1__4__8_12_19_23_42| a b c|__________

为了节省时间,Perl不会费心去除旧数据。它只会释放它,而其他东西可以在需要时随意涂鸦。

这使得推送更加昂贵,特别是对于需要复制更多数据的非常大的阵列。随着阵列越来越大,Perl越来越有可能需要分配一大块内存并复制所有内容。

还有另一个问题:内存碎片。如果你一次又一次地分配和重新分配,那么内存的数量可能会被削减,因此很难找到大块的空闲内存。这在现代操作系统上不是问题,但仍然是一个问题。它可以使你看起来比你真正拥有的内存更少,并且它可以使操作系统将磁盘用作内存(虚拟内存)。磁盘比内存慢。

我简化了很多东西。我让它看起来像每次你push时Perl必须重新分配。事实并非如此。出于这个原因,Perl为数组分配的内存超出了它所需的内存。因此,您可以安全地向数组添加一些额外的条目,而无需重新分配Perl。字符串和哈希值也是如此。

另一件事是,对于内存分配在现代操作系统上的工作方式,这可能是一个有点过时的观点......尽管Perl有时会在不信任操作系统的情况下自行进行内存分配。检查use Config; print $Config{usemymalloc}n表示Perl正在使用操作系统的内存分配,y表示它正在使用Perl。

经验法则是:不要预先分配,这可能是浪费你的时间和计算机的记忆。但是,如果以下条件的所有都为真,请查看预分配是否有帮助。

  • profiled并发现问题。
  • 您正在通过添加来逐步构建数据结构。
  • 您肯定知道它的最小尺寸。
  • 那个大小是“大”。

什么是“大”是有争议的,取决于您的Perl版本,您的操作系统,硬件和性能容差。