简体   繁体   English

如何在长时间运行的Perl程序中找到内存泄漏?

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

Perl uses reference counting for GC, and it's quite easy to make a circular reference by accident. Perl使用GC的引用计数,并且很容易意外地进行循环引用。 I see that my program seems to be using more and more memory, and it will probably overflow after a few days. 我看到我的程序似乎使用了越来越多的内存,并且它可能会在几天后溢出。

Is there any way to debug memory leaks in Perl? 有没有办法在Perl中调试内存泄漏? Attaching to a program and getting numbers of objects of various types would be a good start. 附加到程序并获取各种类型的对象将是一个良好的开端。 If I knew which objects are much more numerous than expected I could check all references to them and hopefully fix the leak. 如果我知道哪些对象比预期的要多得多,我可以检查所有对它们的引用并希望修复泄漏。

It may be relevant that Perl never gives memory back to the system by itself: It's all up to malloc() and all the rules associated with that. 可能有必要的是,Perl 永远不会将内存返回给系统:这完全取决于malloc()以及与之相关的所有规则。

Knowing how malloc() allocates memory is important to answering the greater question, and it varies from system to system, but in general most malloc() implementations are optimized for programs allocating and deallocating in stack-like orders. 了解malloc()如何分配内存对于回答更大的问题非常重要,并且它因系统而异,但通常大多数malloc()实现都针对在类似堆栈的订单中分配和解除分配的程序进行了优化。 Perl uses reference-counting for tracking memory which means that deallocations which means (unlike a GC-based language which uses malloc() underneath) it is actually not all that difficult to tell where deallocation is going to occur, and in what order. Perl使用引用计数来跟踪内存,这意味着解除分配意味着(与基于GC的语言不同,它使用下面的malloc() )实际上并不是很难分辨释放将在何处发生,以及在什么顺序。

It may be that you can reorganize your program to take advantage of this fact- by calling undef($old_object) explicitly - and in the right order, in a manner similar to the way C-programmers say free(old_object); 可能你可以重新组织你的程序以利用这个事实 - 通过显式调用undef($old_object) - 并以正确的顺序,以类似于C程序员说free(old_object);

For long-running programs (days, months, etc), where I have loads of load/copy/dump cycles, I garbage-collect using exit() and exec() , and where it's otherwide unfeasible, I simply pack up my data structures (using Storable ) and file descriptors (using $^F ) and exec($0) - usually with an environment variable set like $ENV{EXEC_GC_MODE} , and you may need something similar even if you don't have any leaks of your own simply because Perl is leaking small chunks that your system's malloc() can't figure out how to give back. 对于长时间运行的程序(天,月等),我有大量的加载/复制/转储循环,我使用exit() and exec()垃圾收集,并且在其他地方不可行的情况下,我只是打包我的数据结构(使用Storable )和文件描述符(使用$^F )和exec($0) - 通常使用环境变量设置$ENV{EXEC_GC_MODE}即使您没有任何泄漏,也可能需要类似的东西自己仅仅是因为Perl是泄漏小块,你的系统malloc()无法弄清楚如何给予回复。

Of course, if you do have leaks in your code, then the rest of my advice is somewhat more relevant. 当然,如果您代码确实存在泄漏,那么我的其他建议会更加相关。 It was originally posted to another question on this subject , but it didn't explicitly cover long-running programs. 它最初发布在关于这个主题的另一个问题上 ,但它没有明确涵盖长期运行的程序。


All perl program memory leaks will either be an XS holding onto a reference, or a circular data structure. 所有perl程序内存泄漏都将是保存在引用上的XS,或者是循环数据结构。 Devel::Cycle is a great tool for finding circular references, if you know what structures are likely to contain the loops. 如果您知道哪些结构可能包含循环,则Devel :: Cycle是查找循环引用的绝佳工具。 Devel::Peek can be used to find objects with a higher-than-expected reference count. Devel :: Peek可用于查找引用计数高于预期的对象。

If you don't know where else to look, Devel::LeakTrace::Fast could be a good first place, but you'll need a perl built for debugging. 如果你不知道在哪里看, Devel :: LeakTrace :: Fast可能是一个很好的第一名,但是你需要一个用于调试的perl。

If you suspect the leak is inside XS-space, it's much harder, and Valgrind will probably be your best bet. 如果你怀疑泄漏是在XS空间内,那就更难了, Valgrind可能是你最好的选择。 Test::Valgrind may help you lower the amount of code you need to search, but this won't work on Windows, so you'd have to port (at least the leaky portion) to Linux in order to do this. Test :: Valgrind可以帮助您减少搜索所需的代码量,但这不适用于Windows,因此您必须将(至少泄漏部分)移植到Linux才能执行此操作。

Devel :: Gladiator是这个领域的另一个有用的工具。

Seems like the cpan module Devel::Cycle is what you are looking for. 看起来像cpan模块Devel :: Cycle就是你要找的东西。 It requires making some changes to your code, but it should help you find your references without too many problems. 它需要对您的代码进行一些更改,但它应该可以帮助您找到您的引用而不会出现太多问题。

valgrind is a great linux application, which locates memory leaks in running code. valgrind是一个很棒的linux应用程序,用于查找运行代码中的内存泄漏。 If your Perl code runs on linux, you should check it out. 如果您的Perl代码在linux上运行,您应该检查它。

In addition to the other comments, you may find my Perl Memory Use talk at LPW2013 useful. 除了其他评论,您可能会发现我在LPW2013上的Perl Memory Use演讲很有用。 I'd recommend watching the screencast as it explains the slides and has some cute visuals and some Q&A at the end. 我建议观看截屏,因为它解释了幻灯片,最后有一些可爱的视觉效果和一些问答。

I'd also suggest looking at Paul Evans Devel::MAT module which I mention in the talk. 我还建议看一下我在演讲中提到的Paul Evans Devel :: MAT模块。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM