Changes in how memory allocation works since MicroPython v1.11 (to v1.20) #12050
Replies: 2 comments 4 replies
-
To answer your specific question -- the main thing that has changed between v1.11 and v1.20 with regard to memory is likely to be the total amount of IDF heap available to micropython. In earlier versions of the IDF they laid out things differently in memory which left a larger contiguous region available for microptyhon to use. That said... this code could be significantly more optimised for memory use. The main thing is that the code uses lists where it should be using e.g. this line:
which allocates a 1950 element list, where each element is a 4-byte integer. Instead it should be
which will be 1/4 the size. Also this should be done once at startup, rather than once per frame, to avoid fragmentation. Similar sort of stuff in ov2640_constants.py which creates a list of 190 list objects (16 byte each), each with 2 4-byte integers (so 4560 bytes, but should just be a bytes constant
taking up 380 bytes instead. The code that accesses this would need to be updated to no longer use the two-level indexing, but that's easy to fix. There is also a lot of unnecessary small allocations which is going to lead to fragmentation. For example:
creates a list and a bytes object for every byte that is written. Instead, something like:
would avoid all of those allocations. |
Beta Was this translation helpful? Give feedback.
-
@cole-morrel Please allow me to consult a loosely related question under this post. @jimmo Upon seeing your reply, it prompted thoughts about my own code. from machine import ADC
import math
import asyncio
adc = ADC(4)
adc.width(ADC.WIDTH_12BIT)
adc.atten(ADC.ATTN_11DB)
class TaskManager:
def __init__(self):
self.list1 = []
self.list1_len = 100
self.average = None
async def mean(self):
self.average = sum(self.list1) / self.list1_len
async def get_list(self):
while True:
x = adc.read_uv()
self.list1.append(x)
if len(self.list1) > self.list1_len:
self.list1.pop(0)
await asyncio.sleep(0)
async def print_average(self):
while True:
if len(self.list1) == self.list1_len:
await self.mean()
if self.average is not None:
print(self.average)
await asyncio.sleep(1)
async def main():
manager = TaskManager()
task = (manager.get_list(), manager.print_average())
await asyncio.gather(*task)
# await asyncio.wait_for(ayncio.gather(*tasks), timeout=30)
asyncio.run(main()) I'm trying to learn asyncio recently and try to apply it, of course this problem may be weakly related to asyncio. My question is, shouldn't I be using list operations in the coroutine |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello, I am trying to use an OV2640 arducam with my ESP32 and I found this (https://github.com/cj667113/micropython-ov2640) repository that does work. However, it does not work in more recent releases of MicroPython (it gives an error about memory allocation in the ov2640.py file, specifically about lines 79 and 105), and as I've tested it so far, only works in the version it was written in which is 1.11. I would like to update this code so that it works in 1.20, but I'm a little confused what the issue is and how to go about fixing it. The ESP32 I'm using clearly has the necessary memory (as it works on an older version), so I assume this is an issue with how the memory is being managed/allocated. The only other warning I get is about I2C being deprecated, and saying to use SoftI2C, but when I change that it does nothing to fix the issue. Sorry if any of this was confusing, I'm fairly new to MicroPython and still trying to learn. Any help would be greatly appreciated.
Beta Was this translation helpful? Give feedback.
All reactions