Page 1 of 1

How do I free this memory?

Posted: Sun Jan 20, 2008 9:46 am
by pdwyer
In the code below:
At the first messagebox the mem usage of the exe in task manager is about 6mb. I hit ok and it jumps to 26mb (assumably due to the space() usage and the string). When I click the second ok it drops by 10mb to 16mb due to cleaning up the loadstring variable.

How do I get the app back to 6mb?

Code: Select all

MessageRequester("first","")
loadstring.s = Space(10000000)
MessageRequester("before","")
loadstring = ""
MessageRequester("after","")
I suspected a leak when I noticed this but if I put space() in a loop it doesn't leak any more than (haven't tested if it's the first or the largest)

Posted: Sun Jan 20, 2008 9:56 am
by Hroudtwolf
Hi,

From codearchiv.

Code: Select all

Procedure FreeString_ASM(*TheString) 
  !MOV edx, 0 
  !LEA ecx, [p.p_TheString] 
  !CALL SYS_FastAllocateStringFree 
  ProcedureReturn 
EndProcedure
Best regards

Wolf

Posted: Sun Jan 20, 2008 10:53 am
by pdwyer
Either you didn't understand the question or I'm not understanding the answer :D

When the string "Loadstring" is set to "" then the 10mb of spaces assigned to it are cleaned up and the memory usage drops. There was 10mb of memory also used somehow "under the hood" from using the space() command.

If I have freed up "loadstring" already, it's that other bit. Perhaps if I do the space() command in a fucntion then it will clean up when it goes out of scope :?:

I tried using your function anyway

Code: Select all

Procedure FreeString_ASM(*TheString) 
  !MOV edx, 0 
  !LEA ecx, [p.p_TheString] 
  !CALL SYS_FastAllocateStringFree 
  ProcedureReturn 
EndProcedure 

MessageRequester("first","")

loadstring.s = Space(10000000)

MessageRequester("before","")

FreeString_ASM(@loadstring)

MessageRequester("after","")
but the effect is the same

Posted: Sun Jan 20, 2008 1:23 pm
by Dare
Hi mate,

I am no expert on these sorts of things, but I had thought (usually a dangerous event).

Is it possible that the memory was freed but windows has not got around to or bothered to release the memory yet? There is something nagging at the back of my mind (and not one of the females in the house!) that suggests this is sometimes the case.

But as I say, I know next to doodly squat to treat this accordingly.

Posted: Sun Jan 20, 2008 3:07 pm
by pdwyer
hmmm,

It's not a time thing, with the msgbox open I can just let it sit there for a while, and only the 10mb is cleaned from the string and not whatever happened with the space().

There was an API and I can't for the life of me remember what it was, that shrinks the mem/virtual mem used by a process to only what it was actually using and paged the rest out. It was handy if you wanted to create a little quiet agent that was really low on resouce usage. perhaps that could do come cleanup then.

this seems quite odd though. It holds onto the largest allocation of space. in the code below it goes as high as 200mb slowly but will not free up the last 100mb

Code: Select all


MessageRequester("first","")

For i = 1 To 10
    loadstring.s = Space(10000000 * i)
    Delay(2000)
    loadstring = ""
Next
MessageRequester("before",Str(Len(loadstring)))

loadstring = ""

MessageRequester("after","")


Posted: Sun Jan 20, 2008 3:21 pm
by tinman
PB uses an internal buffer to manipulate the strings.

Perhaps if you've caused it to be 10MB then it may not have been freed (i.e. it stays at the largest used size).

But that's pure speculation, you'd need to get one of the team to confirm whether that's what happens.

Posted: Sun Jan 20, 2008 7:03 pm
by Psychophanta
Fr34k solution here: Freeing Strings

Posted: Sun Jan 20, 2008 8:08 pm
by Trond
Forget about creative ways to free the string, it won't work.

Posted: Sun Jan 20, 2008 8:36 pm
by Rook Zimbabwe
I have had many problems with freeing memory and clearing buffers. Perhaps t should be a new request in the next version of PB? 8)

Posted: Mon Jan 21, 2008 1:04 am
by pdwyer
@Psychophanta: I don't think this is the same as I'm not trying to free the memory of a string, I'm trying to free some temp memory used by space()

@Trond: Could you elaborate a little?

It looks kind of ugly from task manager.

I wonder if there's any other functions like space() that do this :?

I suppose there's one way to find out if it's actually in use or not... use it all and see what happens :twisted:

Posted: Mon Jan 21, 2008 12:13 pm
by Fred
Yes, PB use an internal buffer to manipulate quickly the strings. It is always set to the larger size you use in a string function (for now, it nevers shrink for performance reason, but we planned to add a counter and resize it after a few smaller calls).

Posted: Mon Jan 21, 2008 2:12 pm
by case
if this have a performance hit why not adding a command for us to free it ourself when we don't need perfomance or just after we use a really large string. maybe a flushstringbuffer() command ? as for a normaly sized string this is not really important that the memory get still ocuped for the buffer as long as the program run.

better imho than a counter so we can control when we wan't to clear it :) as a counter ca in fact release it in a loop when we need performance more:)

Posted: Mon Jan 21, 2008 2:15 pm
by pdwyer
Thanks Fred,

2 Questions:

1: Is there any workaround? I notice that doing this in a function doesn't clean up with fuction returns.

2: Are there any other functions built in to PB that could potentially use large chunks of memory and not return them till app closure? Using several of them could add up.

Cheers

Posted: Mon Jan 21, 2008 3:20 pm
by tinman
Edit 2: fixed code I think.

Here's a hack to resize the internal string buffer, Windows only and needs some assembly. I don't know whether the length of the buffer is set in characters or bytes (which will be important for Unicode) so use at your own risk.

Code: Select all

!extrn _PB_StringBaseSize
!extrn _PB_StringHeap

Define.l string_base
Define.l string_position
Define.l string_heap
Define.l string_size

Gosub GetStringStuff
MessageRequester("Info", "Base=$"+Hex(string_base)+Chr(10)+"Position=$"+Hex(string_position))

foo.s = Space(10000000)
Gosub GetStringStuff
MessageRequester("Info", "Base=$"+Hex(string_base)+Chr(10)+"Position=$"+Hex(string_position))

foo.s = Space(10)
Gosub GetStringStuff
MessageRequester("Info", "Base=$"+Hex(string_base)+Chr(10)+"Position=$"+Hex(string_position))

heap_size.l = HeapSize_(string_heap, 0, string_base)
MessageRequester("Info", "HeapSize="+Str(heap_size))

;- Reset the string size
#HEAP_ZERO_MEMORY = 8
string_base = HeapReAlloc_(string_heap, #HEAP_ZERO_MEMORY, string_base, 16384)
string_size = 16384
EnableASM
    mov eax, dword [v_string_base]
    mov [_PB_StringBase], eax

    mov eax, dword [v_string_size]
    mov [_PB_StringBaseSize], eax
DisableASM

Gosub GetStringStuff
heap_size.l = HeapSize_(string_heap, 0, string_base)
MessageRequester("Info", "HeapSize="+Str(heap_size))

; Little test
foo.s = Space(10)+"blah"
MessageRequester("Test", foo)

; Have we knackered something that caches the length of the heap?
foo.s = Space(10000000)
MessageRequester("Test", "If you got here without a crash, hopefully it worked :)")

End

GetStringStuff:
    EnableASM
    mov eax, dword [_PB_StringBase]
    mov [v_string_base], eax
    mov eax, dword [_PB_StringBasePosition]
    mov [v_string_position], eax
    
    mov eax, dword [_PB_StringHeap]
    mov [v_string_heap], eax
    
    mov eax, dword [_PB_StringBaseSize]
    mov [v_string_size], eax
    
    DisableASM
    Return