-
Notifications
You must be signed in to change notification settings - Fork 2
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
Something must be say about bytearray + readinto #2
Comments
Cool that helps clear up some about your comment about “use bytearray”. But let me be sure I’m clear. If you define a big array in code, then it takes up RAM by
so you’re suggesting that if you keep the array definition in a file somewhere you can load it into a bytearray and save the RAM that would have been used to hold the code. Thanks for the “non-memory-usage-optimized” examples. Any “memory-optimized examples? :) |
The I am totally not sure how an array initialisation in a *.py file consume memory. But the proper way to do it would be a file with all those value (here I don't know exactly the format, because those are not byte or integer, but floating point things. And read that at runtime. You can skip the parsing if you use mpy, then maybe it will be directly into the optimal format. My idea is that the "compilation" of a *.py file into a *.mpy file generated bytecode for your "function" and a "data" segment for the (global) variable you create/initialise. I am totally unsure about "data segment" and "code segment". I believe the memory usage learn guide should be primarly focused on user writing *.py file... not really library writer. I don't know enough about the internal of CP to give really good advice. Like I don't know if a temporary array you use in a function is on the stack or just a pointer in the stack pointing to something allocated on the heap. I would guess it is the later and that most of the memory problem user have are heap memory issue, not stack (except if they use recursive function). Also fighting for memory on an "M0" or a Pico is not the same. Actually, on the Pico or the Feather S2. Sorry, I don't have link to good examples, maybe because most of the code is not too bad? And I only know the place where I would like to fix it when I have time for that. |
Here is the discussion on byte and bytearray and the various way to make that table for the IS32FL3731 library: It might help. |
Based on the two recent CircuitPython meeting, it is clear that something bust be said about bytearray.
If you only have to store positive integer from 0 to 255, then that is the optimal structure to use as each entry cost one byte, where a list of int might cost 4 bytes per entry.
So if short table of short value are needed, putting them as bytearray is beneficial, making a list of tuple would be overkill as the list is an object, each tuple is an object and each int take some space.
A typical bad example is this table: https://github.com/adafruit/Adafruit_CircuitPython_IS31FL3731/blob/9993369654a47ca8763b0971e1dc847717b21cc6/adafruit_is31fl3731/keybow2040.py#L67 :
All values are between 0 and 255 and with a code a little bit smarter, it can be an array of 48 bytes.
If the needed data are big, then reading them from file into a bytearray rather than to declare that in the code will make the code smaller and the memory usage more efficient. Typically a map for a game (containing reference to background tile) could be into a resource file.
One way to avoid memory activity that has a cost in fragmentation and CPU, it is best to use any function that do "readinto" an existing buffer. And that buffer should be the same everytime we have to read (like when you change level in a game). This mean a local variable in a function allocated on the stack at each call is worst than a global (to the library) variable.
Bad example are like this: https://github.com/adafruit/Adafruit_CircuitPython_MLX90640/blob/2668229b7b72dcfc2317c1e607be8ecb1c505cd9/adafruit_mlx90640.py#L123
Every time this function is called, for every "image" a new temporary array of 834 element is created:
Since you only make one call at a time to getFrame, it can be a more global and always the same buffer.
Maybe blurring the distinction between memory on the stack and memory in the heap is not great... and I don't exactly know how CP work inside and what is stored where, so this can give general idea on what to do or not to do.
The text was updated successfully, but these errors were encountered: