Custom port A9G module: help wanted

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: Custom port A9G module: help wanted

Post by jickster » Sun Apr 28, 2019 3:47 pm

pulkin wrote:OK, to try this out I need to also enable gc. So my question is: what does micropython gc actually do? What is the difference between micropython running with gc and without it?
gc frees RAM once an object goes out of scope or is deleted.

It depends on your exact code but generally Without gc you’ll run out of memory because you won’t free memory that’s no longer in use.

But I really want to emphasize that this totally depends on your py code. It’s absolutely possible to have useful code that runs forever that doesn’t need gc.

In fact even if you have gc on you could run out of memory due to fragmentation.




Sent from my iPhone using Tapatalk Pro

pulkin
Posts: 49
Joined: Tue Feb 19, 2019 10:22 pm

Re: Custom port A9G module: help wanted

Post by pulkin » Sun Apr 28, 2019 5:59 pm

Thank you. I understand and agree with what you are saying. I am just interested in some more details.

So, there is my port and there is, for example, esp8266 port. My port has all gc initialization literally commented out:

mpconfigport.h:

Code: Select all

35 // #define MICROPY_ENABLE_GC                   (1)
main.c:

Code: Select all

168     // TODO: gc_init(?, ?);
218     // TODO: gc_sweep_all();
while 8266 port reads this:
mpconfigport.h:

Code: Select all

19 #define MICROPY_ENABLE_GC           (1)
50 #define MICROPY_PY_GC               (1)
main.c:

Code: Select all

46 STATIC char heap[36 * 1024];
52     gc_init(heap, heap + sizeof(heap));
95     gc_sweep_all();
The code is crystal clear but I do not understand
1. what is this heap for,
2. what data is stored in this heap, and
3. where would this data be stored otherwise (i.e. without compiling gc).
4. Does the presence of heap/gc affect, for example, the location of string contents created by mp_obj_new_str?

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: Custom port A9G module: help wanted

Post by jickster » Thu May 02, 2019 2:14 am

pulkin wrote:Thank you. I understand and agree with what you are saying. I am just interested in some more details.

So, there is my port and there is, for example, esp8266 port. My port has all gc initialization literally commented out:

mpconfigport.h:

Code: Select all

35 // #define MICROPY_ENABLE_GC                   (1)
main.c:

Code: Select all

168     // TODO: gc_init(?, ?);
218     // TODO: gc_sweep_all();
while 8266 port reads this:
mpconfigport.h:

Code: Select all

19 #define MICROPY_ENABLE_GC           (1)
50 #define MICROPY_PY_GC               (1)
main.c:

Code: Select all

46 STATIC char heap[36 * 1024];
52     gc_init(heap, heap + sizeof(heap));
95     gc_sweep_all();
The code is crystal clear but I do not understand
1. what is this heap for,
2. what data is stored in this heap, and
3. where would this data be stored otherwise (i.e. without compiling gc).
4. Does the presence of heap/gc affect, for example, the location of string contents created by mp_obj_new_str?
1. Heap is a contiguous block of memory that uPy uses for dynamically created objects.
2. Anything created at runtime
3. gc is separate from heap. You don’t need gc but you do need heap.
4. You need a heap to create new strings.


Sent from my iPhone using Tapatalk Pro

pulkin
Posts: 49
Joined: Tue Feb 19, 2019 10:22 pm

Re: Custom port A9G module: help wanted

Post by pulkin » Mon May 06, 2019 7:26 am

Regarding p.3: I do not have any explicit heap initialization but it still works somehow. ESP8266 port runs gc_init(heap, heap+sizeof(heap)). What is this invocation? What is this heap? Obviously, it is not necessarily the actual heap: the 36Kb chunk 'heap' may appear inside a global stack. Where do I define heap limits in micropython?

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Custom port A9G module: help wanted

Post by dhylands » Mon May 06, 2019 2:59 pm

The call to gc_init is what initializes the heap. In micropython, ALL memory allocations come from the heap.

pulkin
Posts: 49
Joined: Tue Feb 19, 2019 10:22 pm

Re: Custom port A9G module: help wanted

Post by pulkin » Tue May 07, 2019 11:18 am

You confuse me a lot now. I have a working port without gc_init.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Custom port A9G module: help wanted

Post by dhylands » Tue May 07, 2019 2:09 pm

Well I don't know how you can possibly have a working port without a call to gc_init.

arlucio
Posts: 1
Joined: Sat May 18, 2019 1:22 am

Re: Custom port A9G module: help wanted

Post by arlucio » Sat May 18, 2019 5:08 am

I've been working also with the A9 module, I was having some out-of-memory errors and decided to dive deeper.

So first, to understand better how memory works on Micropython and the heap/stack division, I suggest this video and this 2 pages that helped me a lot:

https://www.youtube.com/watch?v=d7qEzpnkWaY&t
https://www.adafruitdaily.com/2017/03/3 ... -mem_info/
https://docs.micropython.org/en/latest/ ... d.html#ram

You can check in your program how the memory is getting allocated using micropython.mem_info() from micropython module. Use gc.collect() from gc module to free blocks that are not been used anymore on the heap, you can see it working on code. Right now you will get something like this from mem_info():

stack: 664 out of 31744
GC: total: 3968, used: 1376, free: 2592
No. of 1-blocks: 4, 2-blocks: 3, max blk sz: 16, max free sz: 33

So the stack size is about 32000 but the heap size is just 3968, that's pretty low. For comparison, the A9 has 4 MB of SRAM, I have one esp32 that has only 520Kb and reads like this:

stack: 736 out of 15360
GC: total: 120064, used: 65888, free: 54176
No. of 1-blocks: 35, 2-blocks: 4, max blk sz: 1250, max free sz: 3281

So definitely there is something wrong. The most important value here is the total value on the GC: line, that's the heap memory size that is used for about every command we give in uPy.

From what I got to understand of this port, is that it uses the C++ CSDK to create the main thread that is always necessary (as pointed here https://ai-thinker-open.github.io/GPRS_ ... -code.html) and than it creates a second thread that is the micropython thread. This threads is called MycroPyTask and it defines the stack and heap size, and also starts the gc. This all happens on main.c, basically on this part:

stack_top = info.stackTop + info.stackSize * 4;
mp_stack_set_top((void *)stack_top);
mp_stack_set_limit(MICROPYTHON_TASK_STACK_SIZE * 4 - 1024);
uint16_t heap_size;
heap = mp_allocate_heap(&heap_size);
gc_init(heap, heap + heap_size);

So checking there, the stack size is set for 2048 * 4 * 4 -1024, exactly the 31744 that appears at the stack size when we run mem_info().
Also, heap size is set as h_size = 4 * 1024, that is 3968 from the heap total +128bits that mem_info uses. I decided to play with these values, when changing stack size value I couldn't connect anymore to the module, tried some different values and went back to the one it is. Changing heap size values was a success, I've tried many different ones and the best I got was 59968, so almost 60k from what was 4k. I used h_size = 2048 * 30 for this. I've tested the available heap memory by allocating buffers and could use all this memory. Right now mem_info() gives me:

stack: 664 out of 31744
GC: total: 59968, used: 448, free: 59520
No. of 1-blocks: 11, 2-blocks: 5, max blk sz: 4, max free sz: 3713

so, no more out of memory problems. I believe we still can get higher values somehow, esp32 has only 1/8 of the A9 RAM and got about the double of the heap size that I got.

Quite a big text if any part is confusing/any doubt just ask me.

pulkin
Posts: 49
Joined: Tue Feb 19, 2019 10:22 pm

Re: Custom port A9G module: help wanted

Post by pulkin » Sun May 19, 2019 5:01 pm

Well, the question is how much contiguous memory can be allocated. I will stick to 512k (well, a binary search can be applied here but I do not think it is import right now). The good news is that mp finaliser is working! Deleting a file pointer and calling gc.colllect will actually close the file!

Yet, the port was working without gc at all and it seems mysterious. MP could even throw OOM at some point.

Another gc-related question I have right now is: whether is is important to look into registers for root pointers in a single-threaded mp?

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: Custom port A9G module: help wanted

Post by jickster » Sun May 19, 2019 5:08 pm

Yes it’s important. If you don’t you could delete an object erroneously.


Sent from my iPhone using Tapatalk Pro

Post Reply