Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Not able to release memory

by asinghvi (Acolyte)
on Mar 03, 2004 at 06:01 UTC ( #333464=perlquestion: print w/replies, xml ) Need Help??
asinghvi has asked for the wisdom of the Perl Monks concerning the following question:

Perl gurus,
I am trying to address some memory limitation in my perl program. While doing my research, I was curious to see how memory gets released in perl once a variable goes out of scope.
I have the following code:
#!/usr/bin/perl undef %hash1; foreach ($i=1;$i<=1000;$i++) { foreach ($j=1;$j<=100;$j++) { foreach ($k=1;$k<=100;$k++) { $hash1{"$i^$j^$ik"} = 1; } } } print "Check Memory usage NOW\n"; sleep 10; undef %hash1; print "And Now\n"; sleep 10;
I see that when the data is loaded, the memory of this process is (e.g. 200MB). But after destructing "%hash1", I don't see any change in the perl process/residual memory. Isn't it supposed to reduce the process size of the perl process.
Am I missing something here

Thanks in advance for your help

Replies are listed 'Best First'.
Re: Not able to release memory
by davido (Archbishop) on Mar 03, 2004 at 06:08 UTC
    Perl may be done using that memory for the moment, but virtually all OS's don't reclaim it. However, if you were to rebuild another data-structure that needed gobs of memory, the same memory would be reused within your current process.

    Update: I should mention that if you really need to force your OS to reclaim memory, you should start looking at using exec to spawn a new process while terminating the current one. Of course you may need to figure out a solution to maintain state, but that's another discussion.


      ++ davido, Some of the reasons that most OS will not reclaim memory very much or at all until the process exits are: Fragmentation -- are the small chunks of memory released valuable to other applications? If so does the OS have to restructure and virtualize the memory so that the free blocks are contiguous? At what cost?

      Unix processes tend to live in two forms, quick running (ls, cat, du) and long running (syslog, inetd, oracle). For quick running processes the process will be over soon enough and the memory free issue is moot. For long running processes the process will generally need to alloc more memory anyways, may as well make it easy and quick by leaving it for the next alloc. This happens at little expense to your physical RAM as while that memory is freed the chunk can be swapped out and used by other applications.

      You will see that on most modern unices that large block (one alloc, one free) tend to be reabsorbed by the OS -- although for instance on Solaris with an app compiled with gcc you will not see this. it all depends on the OS, the compiler and the libraries used. Not really a perl issue.

      In my case, I have Tk application running in Win32 environment that never exits. Some of my variables get very large data and as a result - after a period of time, my application "eats" the memory of Windows, and windows complain that the virtual memory is too low. Most of the time - as a result of this - the application gets destroyed by Windows. What I recently found is that if one click with the mouse on the Minimize button of the Tk window, Windows is claiming back the unused memory from perl and everything goes back to normal. For example: from 128MB wperl.exe in the memory, the process size goes to 2MB. Then it starts growing again - until next time you minimize the window. So what I was thinking is that there must be an API call that identifies the process and ask the OS to require the garbige. Correct me if I am wrong. I saw this happens with many applications in Windows. I am desperate for solution about this - because I need to finish my project :(( any help is welcome. Thanks!!!
Re: Not able to release memory
by eyepopslikeamosquito (Chancellor) on Mar 03, 2004 at 07:24 UTC

    A while back, I did a simple test of mallocing a 4 MB chunk of memory, then freeing it. The memory was returned to the OS on Windows and Linux -- but not on every other of the 12 different platforms I ran the test on.

    Whether the memory is returned to the OS or not depends on the implementation of the user-level malloc function. Most implementations of malloc simply call sbrk(2) to increase the address space of the process. Since this call is expensive, when you call free, they typically do not return the memory to the OS, but keep it to reuse next time you call malloc.

    glibc 2.x based Linux systems use ptmalloc, which is based on Doug Lea's malloc. This version of malloc is able to return memory to the OS because it uses mmap(2), rather than sbrk, when the chunk of memory requested is larger than some threshold value (typically 128K). MSVC CRT similarly uses a "small block" and "large block" heap heuristic -- but uses Win32 heaps, rather than sbrk/mmap, under the covers.

    So, if you were desperate to have memory returned to the OS, you could go to the bother of building a custom perl which used a different implementation of malloc.

Re: Not able to release memory
by demerphq (Chancellor) on Mar 03, 2004 at 08:19 UTC

    Ok, there are a few things.

    First as others have commented the OS manages allocating and freeing memory, and typically doesnt bother. But with modern OS'es swapping etc, im not sure why it should be a problem, maybe on *nix its different to win32.

    Second you are creating 1000 * 100 * 100 keys, which means 10,000,000 keys, which also means a hash stucture of 16,777,216 value slots as internally there will always be next power of 2 value slots vs keys. The best way to reduce the memory footprint of something like this is to use a DB or a hash tied to a DB of some form, possibly cached by a real hash for speed on frequent fetches. A tied DB_File B+Tree is often a reasonable option.

    Third your style is ah, very C like. :-)

    #!/usr/bin/perl -w use strict; my %hash; for my $i (1..1000) { for my $j (1..100) { for my $k (1..100) { $hash{$i,$j,$k} = 1 } } } print "Check Memory usage NOW and press enter\n"; my $chk=<>; %hash=(); print "Check Memory usage NOW and press enter\n"; $chk=<>;



      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi

Re: Not able to release memory
by kvale (Monsignor) on Mar 03, 2004 at 06:05 UTC
    In most Unices, process memory is not 'given back' to the OS until the process finishes.


Re: Not able to release memory
by eyepopslikeamosquito (Chancellor) on Mar 03, 2004 at 11:13 UTC

    Just a couple of random extra thoughts that may be of interest. To find the memory usage of Perl variables, try the Devel::Size module (by a very distinguished and busy Perl-6 architect, I see;-).

    To pre-size a hash, use the keys function as a l-value; see perldoc -f keys for details. That is, if you know in advance that the hash is going to be very big, pre-sizing it will certainly improve speed, and may improve memory usage a little (untested).


Re: Not able to release memory
by Roger (Parson) on Mar 03, 2004 at 07:35 UTC
    Not possible with standard ActiveState Perl under Windows. However Perl can be compiled from source to use custom malloc/dealloc/realloc functions, provided by the Windows operating system (you will probably need to write a wrapper for it), instead of using Perl's own. Which will almost certainly suffer in performance, but will be more memory friendly.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://333464]
Approved by kvale
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (4)
As of 2017-03-24 05:42 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (296 votes). Check out past polls.