http://qs321.pair.com?node_id=566041


in reply to releasing memory from a loop in Windows

How are you measuring the memory footprint? If you do it from the perspective of the OS: I don't think perl returns freed memory back to the OS for the running time of the program. I thought that this is a general thing (not just perl), but this is all hearsay so perhaps someone can clarify (rather than get carried away by the exact definition of 'garbage collection').

Replies are listed 'Best First'.
Re^2: releasing memory from a loop in Windows
by BrowserUk (Patriarch) on Aug 08, 2006 at 01:52 UTC

    Under some circumstances, Perl (AS) under Win32 will release memory back to the OS.

    To demonstrate this, in the following snippet 'tasklist.exe', an MS executable, is used to query the OS for the current memory allocation for the current perl process before and after the allocation of a 100 MB chunk of memory, and again after the Perl scalar containing that memory is undef'd:

    c:\test>p1 [0] Perl> system qq[tasklist /fi "PID eq $$"];; Image Name PID Session Name Session# Mem Usag +e ========================= ====== ================ ======== =========== += perl.exe 888 0 2,972 +K [0] Perl> open RAM, '>', \$ram;; [Bad file descriptor] Perl> print RAM 'X' x 1e6 for 1 .. 100; print le +ngth $ram;; 100000100 [0] Perl> system qq[tasklist /fi "PID eq $$"];; Image Name PID Session Name Session# Mem Usag +e ========================= ====== ================ ======== =========== += perl.exe 888 0 101,008 +K [0] Perl> close RAM;; [0] Perl> undef $ram;; [0] Perl> system qq[tasklist /fi "PID eq $$"];; Image Name PID Session Name Session# Mem Usag +e ========================= ====== ================ ======== =========== += perl.exe 888 0 3,256 +K

    At startup, the perl executable is using just under 3 MB of ram.

    After the allocation of 95.36 MB (100 * 1e6) of memory to a Perl scalar (via a ramfile), the memory allocated to the executable stands at just over 101 MB.

    After the ramfile is closed and the variable $ram is undef'd, the memory allocated to the process falls back to just over 3MB.

    This occurs because, under Win32, large allocations of ram are allocated and freed using calls directly to the OS. See win32\vmem.c. Specifically, the freeing of memory allocated to the process back to the OS occurs in the following destructor (~ Vmem.c:510 in the source tree):

    VMem::~VMem(void) { #ifndef _USE_BUDDY_BLOCKS ASSERT(HeapValidate(m_hHeap, HEAP_NO_SERIALIZE, NULL)); #endif WALKHEAPTRACE(); DeleteCriticalSection(&m_cs); #ifdef _USE_BUDDY_BLOCKS for(int index = 0; index < m_nHeaps; ++index) { VirtualFree(m_heaps[index].base, 0, MEM_RELEASE); <<<<<<<<< HERE! } #else /* !_USE_BUDDY_BLOCKS */ #ifdef USE_BIGBLOCK_ALLOC for(int index = 0; index < m_nHeaps; ++index) { if (m_heaps[index].bBigBlock) { VirtualFree(m_heaps[index].base, 0, MEM_RELEASE); <<<<< HERE! } } #endif BOOL bRet = HeapDestroy(m_hHeap); ASSERT(bRet); #endif /* _USE_BUDDY_BLOCKS */ } void VMem::ReInit(void) { for(int index = 0; index < m_nHeaps; ++index) { #ifdef _USE_BUDDY_BLOCKS VirtualFree(m_heaps[index].base, 0, MEM_RELEASE); <<<<<< HERE! #else #ifdef USE_BIGBLOCK_ALLOC if (m_heaps[index].bBigBlock) { VirtualFree(m_heaps[index].base, 0, MEM_RELEASE); <<<<< HERE! } else #endif HeapFree(m_hHeap, HEAP_NO_SERIALIZE, m_heaps[index].base); #endif /* _USE_BUDDY_BLOCKS */ } Init(); }

    See MSDN for further information on the operation of this and related OS apis.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.