Amusements and rantlings about the garbage collector #11804
Replies: 5 comments 9 replies
-
The way you do your tests is highly misleading. import gc
def test():
mbase = gc.mem_alloc()
a = bytearray(2000)
ma = gc.mem_alloc()
b = a[:]
mb = gc.mem_alloc()
c = memoryview(a)
mc = gc.mem_alloc()
print('allocating a took', ma - mbase, 'bytes')
print('allocating b took', mb - ma, 'bytes')
print('allocating c took', mc - mb, 'bytes')
test() allocating a took 2016 bytes |
Beta Was this translation helpful? Give feedback.
-
To elaborate on what @GitHubsSilverBullet is saying -- when you are testing this at the REPL, you are also including all of the allocations done by the compiler to evaluate what you typed in. So the 2400 bytes of The version that @GitHubsSilverBullet shows is far more accurate because you're decoupling the compiler/emitter from the actual test you're doing.
Allocations can't be smaller that 16 bytes (that's one gc block). To answer your questions -- In other words -- gc.threshold allows you to trade performance/latency for GC fragmentation. |
Beta Was this translation helpful? Give feedback.
-
Thanks to all for your feedback. |
Beta Was this translation helpful? Give feedback.
-
A follow-up about modules. My program is composed of about a dozen modules.
and so on... Working at the REPL, after a soft reset, only boot.py executed.
I thought it would be better not to import * but here importing one object consumes the same memory ?! I ask for your feedback. |
Beta Was this translation helpful? Give feedback.
-
Hi Dave @dhylands Could you please take a look at my last comments? A long time ago, in a galaxy far away... https://github.com/orgs/micropython/discussions/11804 Are you suggesting it is a good practice to call a gc.collect() after every import ? If yes, should micropython do it by itself when importing modules? |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I am using a esp8266 with the default GC config:
boot.py
The program uses almost all the RAM. While it is running
it calls gc.collect() and print these gc infos:
mem_alloc = 33664
mem_free = 4288
threshold = 9488
right after it calls a function and aborts
I know that free memory is the sum of all free blocks, not the size of the largest free block.
Spelunking... I found this old discussion:
Memory allocation errors with plenty of space
@dhylands Dave I follow your suggestion: at the REPL, after the program aborts, I run
Output:
Note: I don't call a gc.collect, I want to keep the current heap state.
At the REPL, the allocation of 2000 bytes succeeds.
Dave, you wrote on pyboard the memoryview takes 32 bytes.
Now on esp8266 the memoryview takes 576 byte ?!?!?!
@peterhinch Peter suggested to lower the GC threshold:
How to use the new GC threshold feature?
It doesn't help my program.
I fixed the program in two different ways, each of which, by itself, is sufficient:
gc.threshold(512)
QUESTIONS:
Why does the program stop complaining about 512 bytes ... and after at the REPL a request for 2000 bytes is successful?
Why is the GC threshold set so high in boot.py ?
IMHO on micros with low RAM, it is beneficial to have a much smaller threshold.
Besides possible delays, are there any other side effects of using a threshold of 512 bytes?
I read the docs but don't really understand behaviour of the GC.
Specifically the rationale of the threshold set in boot.py towards the behavior of the GC at runtime.
Beta Was this translation helpful? Give feedback.
All reactions