簡體   English   中英

如何在長時間運行的Perl程序中找到內存泄漏?

[英]How can I find memory leaks in long-running Perl program?

Perl使用GC的引用計數,並且很容易意外地進行循環引用。 我看到我的程序似乎使用了越來越多的內存,並且它可能會在幾天后溢出。

有沒有辦法在Perl中調試內存泄漏? 附加到程序並獲取各種類型的對象將是一個良好的開端。 如果我知道哪些對象比預期的要多得多,我可以檢查所有對它們的引用並希望修復泄漏。

可能有必要的是,Perl 永遠不會將內存返回給系統:這完全取決於malloc()以及與之相關的所有規則。

了解malloc()如何分配內存對於回答更大的問題非常重要,並且它因系統而異,但通常大多數malloc()實現都針對在類似堆棧的訂單中分配和解除分配的程序進行了優化。 Perl使用引用計數來跟蹤內存,這意味着解除分配意味着(與基於GC的語言不同,它使用下面的malloc() )實際上並不是很難分辨釋放將在何處發生,以及在什么順序。

可能你可以重新組織你的程序以利用這個事實 - 通過顯式調用undef($old_object) - 並以正確的順序,以類似於C程序員說free(old_object);

對於長時間運行的程序(天,月等),我有大量的加載/復制/轉儲循環,我使用exit() and exec()垃圾收集,並且在其他地方不可行的情況下,我只是打包我的數據結構(使用Storable )和文件描述符(使用$^F )和exec($0) - 通常使用環境變量設置$ENV{EXEC_GC_MODE}即使您沒有任何泄漏,也可能需要類似的東西自己僅僅是因為Perl是泄漏小塊,你的系統malloc()無法弄清楚如何給予回復。

當然,如果您代碼確實存在泄漏,那么我的其他建議會更加相關。 它最初發布在關於這個主題的另一個問題上 ,但它沒有明確涵蓋長期運行的程序。


所有perl程序內存泄漏都將是保存在引用上的XS,或者是循環數據結構。 如果您知道哪些結構可能包含循環,則Devel :: Cycle是查找循環引用的絕佳工具。 Devel :: Peek可用於查找引用計數高於預期的對象。

如果你不知道在哪里看, Devel :: LeakTrace :: Fast可能是一個很好的第一名,但是你需要一個用於調試的perl。

如果你懷疑泄漏是在XS空間內,那就更難了, Valgrind可能是你最好的選擇。 Test :: Valgrind可以幫助您減少搜索所需的代碼量,但這不適用於Windows,因此您必須將(至少泄漏部分)移植到Linux才能執行此操作。

Devel :: Gladiator是這個領域的另一個有用的工具。

看起來像cpan模塊Devel :: Cycle就是你要找的東西。 它需要對您的代碼進行一些更改,但它應該可以幫助您找到您的引用而不會出現太多問題。

valgrind是一個很棒的linux應用程序,用於查找運行代碼中的內存泄漏。 如果您的Perl代碼在linux上運行,您應該檢查它。

除了其他評論,您可能會發現我在LPW2013上的Perl Memory Use演講很有用。 我建議觀看截屏,因為它解釋了幻燈片,最后有一些可愛的視覺效果和一些問答。

我還建議看一下我在演講中提到的Paul Evans Devel :: MAT模塊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM