2016-04-21 61 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版本,您的操作系統,您的硬件和性能容忍。

相關問題