Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to identify places accumulating memory use in a Perl script?

In my Perl script, it runs with high accumulation speed of occupied memory. I have tried making suspect variables clear immediately when they are no longer needed, but the problem can not be fixed. Is there any method to monitor change of memory occupation before and after executing a block?

like image 219
Ezekiel Kuo Avatar asked May 11 '14 07:05

Ezekiel Kuo


1 Answers

I have recently had to troubleshoot an out-of-memory situation in one of my programs. While I do not claim to be an expert in this matter by any means, I'm going to share my findings in the hope that it will benefit someone.

1. High, but stable, memory usage

First, you should ensure that you do not just have a case of high, but stable, memory usage. If memory usage is stable, even if your process does not fit in available memory, the discussion below won't be of much help. Here are some notes worth reading in Perl's documentation here and here, in this SO question, in this PerlMonks discussion. There is an interesting analysis here if you're familiar with Perl internals. A lot of deep information is to be found in Tim Bunce's presentation. You should be aware that Perl may not return memory to the system even if you undef stuff. Finally, there's this opinion from a Perl developer that you shouldn't worry too much about memory usage.

2. Steadily growing memory usage

In case memory usage steadily grows, this may eventually cause an out-of-memory situation. My problem turned out to be a case of circular references. According to this answer on StackOverflow, circular references are a common source of memory leaks in Perl. The underlying reason is that Perl uses a reference counting mechanism and cannot release circularly referenced memory until program exit. (Note: I haven't been able to find a more up-to-date version in Perl's documentation of the last claim.)

You can use Scalar::Util::weaken to 'weaken' a circular reference chain (see also http://perlmaven.com/eliminate-circular-reference-memory-leak-using-weaken).

3. Further reading

  • Tim Bunce's presentation (slides here); also in this blog post
  • http://www.perlmonks.org/?node_id=472366
  • Perl memory usage profiling and leak detection?
  • and of course the link given by @mpapec: http://perlmaven.com/how-much-memory-does-the-perl-application-use

4. Tools

  • on Unix, you could do system("ps -p $$ -o vsz,rsz,sz,size") Caution: as explained in Tim Bunce's presentation, you'll want to track VSIZE instead of RSS
  • How to find the amount of physical memory occupied by a hash in Perl?
  • https://metacpan.org/pod/Devel::Size
  • and a more recent take by Tim Bunce, which adds the possibility of estimating the total interpreter memory size: https://metacpan.org/pod/Devel::SizeMe
  • in test scripts, you can use https://metacpan.org/pod/Test::LeakTrace and https://metacpan.org/pod/Test::Memory::Cycle; an example here
  • https://metacpan.org/pod/Devel::InterpreterSize
like image 92
Edward Avatar answered Sep 28 '22 05:09

Edward