2016-04-21 27 views
11

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

回答

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越来越可能不得不分配一大块内存并复制所有内容。

还有一个问题:内存碎片。如果你一次又一次地分配和重新分配内存块,那么很难找到大块空闲的内存。这在现代操作系统上不是什么问题,但仍然是一个问题。它可以使您看起来内存少于实际使用的内存量,并且可能导致操作系统将磁盘用作内存(虚拟内存)而不是它应该使用的内存。磁盘比内存慢。


我简化了很多东西。我让它看起来像Perl必须重新分配每当你push。这是不正确的。正因为这个原因,Perl为数组分配更多的内存。因此,您可以安全地向数组添加一些额外的条目,而不必重新分配Perl。对于字符串和哈希也是如此。

另一件事是,这可能是一个过时的观点,如何分配内存在现代操作系统上工作......虽然Perl有时会做自己的内存分配,如果它不信任操作系统。检查use Config; print $Config{usemymalloc}n表示Perl正在使用操作系统的内存分配,y表示它正在使用Perl的。

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

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

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

相关问题