Skip to content

Gathering data on the CircuitPython memory weirdness. #6992

@bill88t

Description

@bill88t

CircuitPython version

Adafruit CircuitPython 8.0.0-beta.1 on 2022-10-01; Raspberry Pi Pico W with rp2040

Code/REPL

from gc import mem_free, collect
from sys import exit

targ_mem = None
mem_offs = 69420 # offset to add, value set to allocate the needed ram

# tests

# for loop test
for_t = False

# int test
int_t = False

mem_offs = 0 # revert the value to 0, so we can actually use it

# script begin

def memstep(fail=True):
    global targ_mem, mem_offs
    collect()
    f = mem_free()
    diff = targ_mem - f + mem_offs
    if diff:
        print("-> Diff: " + str(diff), end="")
        if fail:
            print(" | This is not fine.\n\n--- FAIL ---", end="")
            exit(1)
        else:
            print(" | This is fine.",end="")
        print()
    del f, fail, diff
    collect()

collect()
targ_mem = mem_free()
print(f"\nTarget mem is set to {targ_mem}.")
# fstrings with vars leave collectable garbage
print("\nInitial       test")
memstep()

if for_t:
    print("Before  \"for\" test")
    memstep()
    
    print("In      \"for\" test")
    mem_offs -= 16
    
    for i in range(30):
        memstep()

    mem_offs += 16
    collect()
    print("After   \"for\" test")
    memstep()

if int_t:
    print("In      \"int\" test")
    i = 69420531221
    #collect()
    mem_offs -= 16
    memstep()
    
    print("Del     \"int\" test")
    del i
    mem_offs += 16
    #collect()
    memstep()

print("End           test")
collect()
memstep()

print("--- PASS ---")
exit(0)

Behavior

As is, it works. This means the memstep function and the prints aren't leaving anything behind.

If we now for_t = True, we instead fail:

Target mem is set to 158560.

Initial       test
Before  "for" test
In      "for" test
After   "for" test
-> Diff: 16 | This is not fine.

--- FAIL ---
Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

if the offset wasn't there we would fail within the "for" test.
The outcome doesn't change if I replace the memstep with a pass inside the for loop.

If we then for_t = False and int_t = True, we yet again fail:

Target mem is set to 158560.

Initial       test
In      "int" test
Del     "int" test
-> Diff: 16 | This is not fine.

--- FAIL ---
Code done running.

Press any key to enter the REPL. Use CTRL-D to reload.

What even holds those 16 bytes???????????

Description

No response

Additional information

For anyone who wonders as to why this is important, ljinux runs stuff on a loop pretty much forever, these leaks accumulate into many kilobytes.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions