FlexGUI/FlexBASIC garbage collection/memory alloc question
JRoark
Posts: 1,215
in Propeller 1
As an exercise I’m playing with a DS3232 RTC and using FlexBASIC to read and write to the device via I2C. That part works nicely.
My problem comes when I’m formatting the returned data into a prettier human-readable form. In the process I’m calling a bunch of string handling functions and getting “Out Of Memory” errors immediately. So I increased the HEAPSIZE to 8k. But after 4-5 iterations of printing the date/time, (e.g “Mon Oct 14, 2019 20:34:56”) the problem recurs.
Is there a way to either manually trigger FlexBASIC’s garbage collection, or to maybe create/use/destroy/free a string variable repetitively in a loop to avoid the memory hogging?
The FlexBASIC docs for the NEW and DELETE methods re strings is pretty sparse, but I’ve tried various permutations of these with no success yet.
Any ideas?
My problem comes when I’m formatting the returned data into a prettier human-readable form. In the process I’m calling a bunch of string handling functions and getting “Out Of Memory” errors immediately. So I increased the HEAPSIZE to 8k. But after 4-5 iterations of printing the date/time, (e.g “Mon Oct 14, 2019 20:34:56”) the problem recurs.
Is there a way to either manually trigger FlexBASIC’s garbage collection, or to maybe create/use/destroy/free a string variable repetitively in a loop to avoid the memory hogging?
The FlexBASIC docs for the NEW and DELETE methods re strings is pretty sparse, but I’ve tried various permutations of these with no success yet.
Any ideas?
Comments
Garbage collection isn't perfect, there are times when a local variable or stack location still has a pointer to the memory and hence prevents collection from happening. If you're finding that things aren't being collected, try putting the actual code that manipulates strings into a subroutine and run that subroutine from a loop in the main program; that may help the garbage collector see that the variables are no longer in use.
Moving the string generation code into a SUB had no effect.
Adding “_gc_collect()” to the main loop had no effect.
Adding _gc_collect() to the SUB had no effect.
Adding multiple _gc_collect() calls to SUB and main loop had no effect.
Declaring variables with VAR or DIM at both the SUB and main body levels had no effect. Combinations of all of the above... same-same.
I’m stumped!
Can you post some of the relevant code?
I'm not too surprised that adding _gc_collect() calls had no effect -- you'll never see an "Out of Memory" until after _gc_collect has been tried at least once. Moving things into a subroutine or function often seems to help in my experience, but obviously it depends on the exact code.
One possibility is that you're running into memory fragmentation -- there is memory available, but none of the individual chunks is large enough to satisfy the request.
Another is that for some reason the garbage collector thinks that some memory is still in use when it isn't. You could try adding explicit _gc_free() calls to free some of your strings when you know you're done with them.
The more I play with this, the more I believe it is a fragmentation issue, and having a diagnostic tool like FRE() would be useful.
You could update parts of a string in place without waking the GC dragon.
I played a bit with FlexBASIC and patching chars into a string at an offset and probably someone used to a modern BASIC can do it in a more readable and/or efficient way.
"cast()" and/or other pointer/address tricks might not even look strange to someone being used to modern BASIC: https://forums.parallax.com/discussion/comment/1479178/#Comment_1479178
For me having all this luxury in a BASIC still is like "𝖞𝖊𝖙𝖎 𝖎𝖓 𝖜𝖔𝖓𝖉𝖊𝖗𝖑𝖆𝖓𝖉".
No, there's nothing like FRE() implemented yet. I agree it would be useful, but I haven't had time to do it .