FlexGUI/FlexBASIC garbage collection/memory alloc question

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?

Comments

  • The function to force the garbage collector to run is _gc_collect.

    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.
  • Good stuff @ersmith ! I’ll give it a whirl and see what works.
  • No bueno, @ersmith

    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!
  • JRoark wrote: »
    No bueno, @ersmith

    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.
  • I’ll give it a whirl. If I’m still stuck after _gc_free() I’ll see if I can extract and post the offending segments from the current hairball I call “code”. Hehe.
  • I’m in the process of whittling-down and extracting the offending code from the larger project but have been playing with the _gc_free() and _gc_collect() calls as I go. Using these does delay the crash by quite a bit (10+ iterations) when I use them in SUBs and FUNCTIONs prior to exiting, which brings-up a question: is there a “hidden” function call similar to FRE() that will return the size of the available heap? And maybe the size of the largest contiguous heap chunk?

    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.
  • Which string formats of date and time do you need?

    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 "𝖞𝖊𝖙𝖎 𝖎𝖓 𝖜𝖔𝖓𝖉𝖊𝖗𝖑𝖆𝖓𝖉".
    ◁ propeller-wiki ▷ ◁ FastSpin ▷ ◁ Help Spin at RosettaCode.org ▷ ◁ No Source – No Go! ▷ ◁ DK-E ▷ ◁ :-D ▷ ◁ Stay OmmmmmmPtimistic! ▷ ◁ Why Asimov's Laws of Robotics Don't Work ▷ ◁ DNA is a four letter word. ▷ ◁ Stop slavery! Free all mitochondria! ▷
  • JRoark wrote: »
    I’m in the process of whittling-down and extracting the offending code from the larger project but have been playing with the _gc_free() and _gc_collect() calls as I go. Using these does delay the crash by quite a bit (10+ iterations) when I use them in SUBs and FUNCTIONs prior to exiting, which brings-up a question: is there a “hidden” function call similar to FRE() that will return the size of the available heap? And maybe the size of the largest contiguous heap chunk?

    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.

    No, there's nothing like FRE() implemented yet. I agree it would be useful, but I haven't had time to do it :(.
Sign In or Register to comment.