如何在长时间运行的

如何在长时间运行的

本文介绍了如何在长时间运行的 Perl 程序中找到内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Perl 对 GC 使用引用计数,并且很容易意外地进行循环引用.我看到我的程序似乎使用越来越多的内存,几天后它可能会溢出.

Perl uses reference counting for GC, and it's quite easy to make a circular reference by accident. I see that my program seems to be using more and more memory, and it will probably overflow after a few days.

有没有办法在 Perl 中调试内存泄漏?附加到程序并获取各种类型的对象数量将是一个好的开始.如果我知道哪些对象比预期的多得多,我可以检查对它们的所有引用,并希望修复泄漏.

Is there any way to debug memory leaks in 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.

推荐答案

Perl 从不 自己将内存返还给系统可能是相关的:这完全取决于 malloc() 以及与之相关的所有规则.

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.

了解 malloc() 如何分配内存对于回答更大的问题很重要,它因系统而异,但通常大多数 malloc() 实现都是优化的用于以类似堆栈的顺序分配和解除分配的程序.Perl 使用引用计数来跟踪内存,这意味着释放这意味着(与基于 GC 的语言在下面使用 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. 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.

也许你可以重新组织你的程序以利用这个事实——通过显式调用 undef($old_object)——并以正确的顺序,以类似于 C 的方式——程序员说free(old_object);

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);

对于长时间运行的程序(几天、几个月等),我有大量的加载/复制/转储周期,我使用 exit() 和 exec() 进行垃圾收集,以及这在其他方面是不可行的,我只是打包我的数据结构(使用 Storable)和文件描述符(使用 $^F)和 exec($0)- 通常使用像 $ENV{EXEC_GC_MODE} 这样的环境变量集,并且您可能需要类似的东西即使您自己没有任何泄漏,因为 Perl 是泄漏您系统的 malloc() 无法弄清楚如何回馈的小块.

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.

当然,如果您的代码确实存在漏洞,那么我的其余建议更有意义.它最初发布在 到另一个关于这个主题的问题,但它没有明确涵盖长时间运行的程序.

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.

所有 perl 程序内存泄漏要么是持有引用的 XS,要么是循环数据结构.Devel::Cycle 是查找循环引用的好工具,如果您知道什么结构的话很可能包含循环.Devel::Peek 可用于查找引用高于预期的对象计数.

All perl program memory leaks will either be an XS holding onto a reference, or a circular data structure. Devel::Cycle is a great tool for finding circular references, if you know what structures are likely to contain the loops. Devel::Peek can be used to find objects with a higher-than-expected reference count.

如果你不知道去哪里找,Devel::LeakTrace::快速可能是一个不错的选择,但您需要一个专为调试而构建的 perl.

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.

如果您怀疑泄漏发生在 XS-space 内,那就更难了,Valgrind 可能是您最好的选择.Test::Valgrind 可能会帮助您减少需要搜索的代码量,但是这在 Windows 上不起作用,因此您必须将(至少是泄漏部分)移植到 Linux 才能执行此操作.

If you suspect the leak is inside XS-space, it's much harder, and Valgrind will probably be your best bet. 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.

这篇关于如何在长时间运行的 Perl 程序中找到内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-27 06:13