在刪除元素時,Perl中的哈希值是否會縮小?在刪除元素時,Perl中的哈希值是否會縮小?
更具體地說我不得不說我繼承了將會解析一個巨大的文件(1 GB),並加載了哈希散列Perl程序。它會爲另一個文件做同樣的事情,然後對不同的元素進行比較。在這個過程中內存的消耗是巨大的,即使我添加了刪除哈希元素,但是在內存消耗方面似乎沒有受到影響。
腳本非常慢,這樣的記憶豬。我知道它沒有很好的設計,但有關哈希內存使用的想法?
在刪除元素時,Perl中的哈希值是否會縮小?在刪除元素時,Perl中的哈希值是否會縮小?
更具體地說我不得不說我繼承了將會解析一個巨大的文件(1 GB),並加載了哈希散列Perl程序。它會爲另一個文件做同樣的事情,然後對不同的元素進行比較。在這個過程中內存的消耗是巨大的,即使我添加了刪除哈希元素,但是在內存消耗方面似乎沒有受到影響。
腳本非常慢,這樣的記憶豬。我知道它沒有很好的設計,但有關哈希內存使用的想法?
一般來說,Perl不能將內存返回到操作系統。不過,它可能能夠在內部重用內存,這可以減少程序所需的內存量。
見perlfaq3:How can I free an array or hash so my program shrinks?
如果由散列所使用的存儲器是過度(即>物理存儲器),你可以他們tie
到磁盤上的文件。這將大大減少您的內存使用量,但會被警告,訪問磁盤上的結構比訪問內存中的結構慢得多。 (因此是磁盤顛簸。)
你可能想看看像DBM::Deep東西。它確實提供了邁克爾提到的那些搭配的東西,所以你不必考慮它。一切都存儲在磁盤上而不是內存中。這只是需要一個更好的數據庫服務器。另外,如果您想追蹤性能瓶頸,請查看Devel::NYTProf,這是Perl分析的新熱點,它出自紐約 Times。
如果你的哈希確實是巨大的,一個更好的策略是可能使用磁盤上的哈希,並讓有關把事情進出內存OS擔心。我特別喜歡Berkeley DB用於在磁盤上存儲大型哈希,Perl BerkeleyDB模塊提供了一個全功能的界面,包括一個綁定的API。
DBM::Deep也可以作爲一個下拉哈希更換,而是依靠自己的格式。如果您的結構需要被其他(非Perl)系統讀取,這可能會很痛苦。
如果第二個文件中的輸入只需要一次(當它們被讀取時),則可能會將內存使用量減半。
取決於你的算法,你甚至可以只持有這兩種文件句柄打開,並且不使用的,但在內存中值的小散。一個例子是合併或比較排序後的數據 - 您只需要保存每個文件中的當前行並隨時進行比較,直到cmp
發生變化。
另一種方法可能會進行多次傳遞,特別是如果你在你的機器的一個或多個另外空閒內核。打開讀取管道並讓子流程以可管理的預先組織的塊爲您提供數據。
對於更通用的算法,您只能通過交易磁盤速度成本來避免支付內存大小。
在大多數情況下,將每個數據源加載到內存中僅在開發時獲勝 - 然後在N變大時以足跡和/或速度進行支付。
關於具體問題:不,刪除散列鍵不會減少程序的內存消耗。
關於更一般的情況:絕大多數程序和語言將繼續保留他們以前使用過但尚未使用的內存。這是因爲請求操作系統分配內存是一個相對較慢的操作,所以它們會保存它以備後用。
所以,如果你想改善這種情況,你需要通過修改你的算法,並不需要一次獲得儘可能多的數據使用,以減少你的程序所需的內存峯值量,是否(例如前面提到的DBM :: Deep),或者將不需要的變量的空間釋放回perl(讓它們超出範圍或將它們設置爲undef),以便它可以重用。
解決方法:fork分配所有內存的子進程。讓它在完成它的事情時傳回一些彙總信息;當分叉進程死亡時,其內存將隨之消失。有點痛苦,但適用於某些情況。如果您正在處理多個文件,每次只處理一個文件,只有少數文件很大,並且需要保留少量中間狀態,那麼這有助於實例。