in reply to Re: releasing memory from a loop in Windows
in thread releasing memory from a loop in Windows
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.
|
|---|