Page 1 of 1

After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 3:50 pm
by uwekel
Hi,

today i noticed a large memory use in one of my programs. After some tests i found out a strange behavior with the LIST. I wrote a small sample to point out the problem:

Code: Select all

NewList items.s()

MessageRequester("", "Create") ;memory use is now 2.1 MB

For i = 1 To 5000000
  AddElement(items())
  items() = "This is line number " + Str(i)
Next

MessageRequester("", "Clear") ;memory use is now 384 MB

ClearList(items())

MessageRequester("", "Cleared")  ;memory use is still 233 MB
When reaching the third MessageRequester, i expected the same memory consumption as at the beginning, but there are still 233 MB blocked. Why that?

The debugger was disabled. The code ported into Python 2.7.1 works fine (so it's not Fedora or so).

Best regards
Uwe

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 4:12 pm
by falsam
Test : PB 4.61 Window 7

Code: Select all

NewList items.s()

MessageRequester("", "Create") ;memory use is now 1.8 MB

For i = 1 To 5000000
  AddElement(items())
  items() = "This is line number " + Str(i)
Next

MessageRequester("", "Clear") ;memory use is now 276.6 MB

ClearList(items())

MessageRequester("", "Cleared")  ;memory use is still 3.6 MB

FreeList(items()) ;memory use is still 0.3 MB ........YeahhHHHHH :)
http://www.purebasic.com/documentation/ ... elist.html

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 4:17 pm
by uwekel
I did not mention but i tried already FreeList() with NO effect. The only difference is that the list object itself will be freed. On my system there are still 233 MB used. As you can see in your sample on windows, the main memory consumption must be freed on ClearList().

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 4:34 pm
by uwekel
A test on Fedora 17 32-bit shows the same problem. The maximum memory usage is 262 MB, and will reduce to 195 MB only.

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 4:44 pm
by IdeasVacuum
Interesting one. Your code uwekel works perfectly on Windows XP 32bit, PB4.61, result exactly as expected, Debug off and Debug on.

So, issue is only when on Linux? Any Mac Users out there to test?

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 4:54 pm
by IdeasVacuum
Unexpected result running as a 32bit exe on Win 7 64bit:
Free Ram:
Before 1939MB
List Loaded 1514MB
List Cleared 1949MB

It's OK, but 10MB seems a lot?

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 5:05 pm
by uwekel
The 10 MB is maybe the extra space for the list object. This should be gone after FreeList().

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 5:07 pm
by freak
Never trust programs like the task manager about such things. As long as there is no immediate need for the freed memory, the OS will usually keep it reserved for the program for a possible later allocation. So the number doesn't go down immediately. That doesn't mean that the memory is actually still allocated by the program.

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 5:12 pm
by uwekel
The problem is not caused by the LIST. A test with a string array has a similar result!

Code: Select all

MessageRequester("", "Create") ;memory use is now 2.1 MB

Dim items.s(5000000)

For i = 0 To 5000000-1
  items(i) = "This is line number " + Str(i)
Next

MessageRequester("", "Clear") ;memory use is now 269 MB

ReDim items(0)

MessageRequester("", "Cleared")  ;memory use is still 231 MB

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 5:15 pm
by uwekel
With Integers it works fine!
But why are the strings not be freed?

Code: Select all

NewList items.i()

MessageRequester("", "Create") ;memory use is now 2.1 MB

For i = 1 To 5000000
  AddElement(items())
  items() = i
Next

MessageRequester("", "Clear") ;memory use is now 155 MB

ClearList(items())

MessageRequester("", "Cleared")  ;memory use is still 4 MB

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 5:17 pm
by IdeasVacuum
Freak is of course right - I don't think the empty List would be 10MB though, that will be something else but not important. I used this to verify the RAM on Windows:

Code: Select all

       Import "kernel32.lib"
                  GlobalMemoryStatusEx.i(*lpBuffer)
       EndImport

       Define meminfo.MEMORYSTATUSEX
                  meminfo\dwLength = SizeOf(MEMORYSTATUSEX)

       If GlobalMemoryStatusEx(meminfo)

                     qTotalMem.q = ((meminfo\ullTotalPhys) / 1024 / 1024)
                    qAvailMem.q = ((meminfo\ullAvailPhys) / 1024 / 1024)
                     sRamFree.s = "Free RAM: " + Str(qAvailMem) + "MB"
                     MessageRequester("",sRamFree.s)
       EndIf

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 6:27 pm
by uwekel
@freak: I am using the system monitor from Linux to control the memory consumption. In all above cases, the display seems to be correct, except when strings are involved.

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 7:11 pm
by uwekel
To check if the memory consumption increases more and more, i put the codeblock in a loop and the result was very unexpected: the 384 MB would never be exceeded. So the guess of freak is probably right - the memory is reserved for the current program and will be reused! Nice to know :-)

Code: Select all

NewList items.s()

For j= 1 To 3
  
  MessageRequester("", "Create") ;memory use is now 2.1 MB
  
  For i = 1 To 5000000
    AddElement(items())
    items() = "This is line number " + Str(i)
  Next
  
  MessageRequester("", "Clear") ;memory use is now 384 MB
  
  ClearList(items())
  
  MessageRequester("", "Cleared")  ;memory use is still 233 MB

Next

Re: After clearing a huge list still a lot of memory in use

Posted: Wed Jul 04, 2012 8:31 pm
by xorc1zt

Code: Select all

; purebasic StringHeap stats
; xorc1zt
; 2012
; windows 7

Structure BlockStr
    hMem.i
    dwReserved.l[3]
EndStructure

Structure RegionStr
    dwCommittedSize.l
    dwUnCommittedSize.l
    *lpFirstBlock
    *lpLastBlock
EndStructure

Structure PROCESS_HEAP_ENTRY
    *lpData
    cbData.l
    cbOverhead.b
    iRegionIndex.b
    wFlags.w
    StructureUnion
        Block.BlockStr
        Region.RegionStr
    EndStructureUnion
EndStructure

Procedure PBStringHeapStats (showRegion.b, showUncommitted.b, showBlock.b)
    Define *stringHeap
    Define phe.PROCESS_HEAP_ENTRY
    
    Define totalRegion.i      = 0
    Define totalUncommitted.i = 0
    Define totalBlock.i       = 0
    
    !extrn PB_StringHeap
    !MOV rax, [PB_StringHeap]
    !MOV [p.p_stringHeap],rax 
    
    Debug "--- StringHeap stats ---"
    Debug ""
    
    While (HeapWalk_(*stringHeap, @phe))
        If (phe\wFlags & #PROCESS_HEAP_REGION)   
            totalRegion + 1
            
            If Not (showRegion)
                Continue
            EndIf
            
            Debug "Region:"
            Debug "    bytes committed: "+Str(phe\Region\dwCommittedSize)
            Debug "    bytes uncommitted: "+Str(phe\Region\dwUnCommittedSize)
            Debug "    First block address: "+Hex(phe\Region\lpFirstBlock)
            Debug "    Last block address: "+Hex(phe\Region\lpLastBlock)
        ElseIf (phe\wFlags & #PROCESS_HEAP_UNCOMMITTED_RANGE)      
            totalUncommitted + 1
            
            If Not (showUncommitted)
                Continue
            EndIf
            
            Debug "Uncommitted range:"
        Else
            totalBlock + 1
            
            If Not (showBlock)
                Continue
            EndIf
            
            Debug "Block:"
        EndIf
        
        Debug "    Data portion begins at: "+Hex(phe\lpData)
        Debug "    Size: "+Str(phe\cbData)+" bytes"
        Debug "    Overhead: "+Str(phe\cbData)+" bytes"
        Debug "    Region index: "+Str(phe\iRegionIndex)
        Debug ""
    Wend
    
    Debug "Total:"
    Debug "    Regions: "+Str(totalRegion)
    Debug "    Uncommitteds: "+Str(totalUncommitted)
    Debug "    Blocks: "+Str(totalBlock)
    Debug ""
EndProcedure


; ------------------------------
; ------------ test ------------
; ------------------------------

NewList items.s()


MessageRequester("", "Create") ;memory use is now 1.8 MB

For i = 1 To 5000000
  AddElement(items())
  items() = "This is line number " + Str(i)
Next

PBStringHeapStats(0,0,0)
MessageRequester("", "Clear") ;memory use is now 276.6 MB
ClearList(items())
PBStringHeapStats(0,0,0)
MessageRequester("", "Cleared")  ;memory use is still 3.6 MB
FreeList(items()) ;memory use is still 0.3 MB ........YeahhHHHHH :)