Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MicroPython: Magic C++ Memory Management. #725

Merged
merged 2 commits into from
Mar 27, 2023
Merged

Conversation

Gadgetoid
Copy link
Member

This is more a test to see if I'm barking up the right tree than a fix... yet.

@Gadgetoid Gadgetoid force-pushed the patch-frame-convert-heap branch 3 times, most recently from 2c8b4fe to 31fe29f Compare March 24, 2023 14:46
@Gadgetoid Gadgetoid changed the title PicoGraphics: Fixed buffer for frame convert. MicroPython: Magic C++ Memory Management. Mar 24, 2023
@Gadgetoid
Copy link
Member Author

Okay as a result of sleuthing for #720 I ended up raising micropython/micropython#11116

After raising my concerns in micropython/micropython@c80e7c1

And spending a large amount of time trying to avoid new and delete.

Unfortunately, C++ does a lot of heap allocation that's difficult to control. In fact our project does ~10k and it's a job for Future Phil to figure out why on earth we're using so much heap because that seems extreme.

As a result of hours upon hours of tinkering I finally came up with https://github.com/Gadgetoid/micropython-cppmem which is integrated directly into pimoroni-pico in this PR.

This new module just needs to be linked into a MicroPython build and it takes over all C++ memory allocations in two ways:

  1. All pre-init allocations end up in a 10k, linear, non-freeing memory pool that survives until hard-reset
  2. Once init is done, the module switches into "MICROPYTHON" mode, where new and delete map to m_malloc and m_free respectively.

A side-effect of this approach is that any memory resulting from an implicit or explicit use of new in C++ modules cannot be relied upon to not be garbage collected.

This is to say that all our best practices still apply- if you're allocating something that you want to last for more than one C++ function call then it needs to be allocated with m_new and a pointer to the resulting memory region must be stored on an active MicroPython object. Like how our classes work with pointers to buffers and i2c objects.

This module redirects all pre-init object memory allocations into a static, fixed-sized, linear, non-freeing memory pool.

It then auto-switches into "MICROPYTHON" mode, whereupon all C++ `new` and `delete` calls are remapped to `m_malloc` and `m_free` respectively.
@Gadgetoid
Copy link
Member Author

The builds breaking and failing to start up when the cppmem/micropython module is included before other modules suggest that __attribute__ ((init_priority (65535))) is not global. If this is the case, then moving the wakeup module further up the list of C++ modules could make Badger 2040 / Badger 2040 W wakeup button detection a little more responsive.

@Gadgetoid
Copy link
Member Author

Should probably move the switch to MicroPython heap mode into boot.py since we can be sure it will always run after the MicroPython heap, and C++ objects, have initialised.

@Gadgetoid Gadgetoid marked this pull request as ready for review March 24, 2023 20:29
@Gadgetoid Gadgetoid merged commit c6b4a30 into main Mar 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant