There are also some significant enhancements that can be made to the underlying code to make Micro Python even better. These ideas for enhancements come from feedback from using uPy in real-world applications, and can be split into 2 use-cases.
Improvements for uPy when used on a microcontroller:
- Eliminate heap-memory fragmentation
When running for an extended period of time (usually after allocating large buffers), the heap can become very fragmented, and although there is enough free memory for an allocation, the free memory is not contiguous (all in a row). Such a problem severely limits uPy's use in critical and long-running applications (eg a web server, a quadcopter). Code running on a microcontroller needs to be a lot more robust than desktop software running on a PC, and so special care must be taken to design a robust memory allocator.
It's not clear how to improve uPy's current memory allocator so that fragmentation is reduced. Ultimately I would want to see a solution that completely eliminates fragmentation, so that programs are guaranteed to run indefinitely. Note that heap fragmentation is not because of the use of garbage collection: even with reference counting, or explicit free, you still have the same amount of fragmentation. The 2 ideas I have to eliminate fragmentation are: 1) a copying memory manager/garbage collector, that can move parts of the heap around so as to make contiguous regions available; 2) a fixed-block memory manager than allocates a single block size (eg 16 bytes), and if you want more you must chain multiple blocks (like a filesystem). Both of these ideas are difficult to implement, and will come with a speed and memory cost. But the cost will be worth it if we can get guaranteed memory allocation. - Ability to allocate memory on an interrupt
Interrupts and callbacks play a large role in microcontrollers, especially to get real-time performance, and uPy should have good support for them. Currently you can run code on an interrupt, but you can't allocate heap memory during such an interrupt. The memory allocator can be made re-entrant so that memory can be allocated during an interrupt (steps have been made in this direction already, but more work and testing is needed). With this improvement you could write some very sophisticated control code that responded within a guaranteed time to an external event.
- Eliminate need for any assembler in core
Micro Python currently uses some assembler for exceptions (NLR code) and garbage collection. Removing this dependence, and making it pure C, would make embedding uPy much easier (and would make it possible to use Emscripten to compile uPy to Javascript to run it in the browser). NRL code can use setjmp/longjmp, but it would be nice to have the option to use, eg, native C++ exceptions, or something like that. - Eliminate all global state
Embeddable languages (eg Lua) don't have any (much?) global state, and instead pass around a pointer to the interpreter state as the first argument to all functions. This keeps the state self-contained, and allows multiple instances of the language to run in the same process/thread. uPy doesn't need this feature for microcontroller use, but it would be very useful to have for embedded use. It's a straight-forward thing to implement, but touches all functions in the entire code base, and will increase code size, stack usage, and reduce speed.
Are there any ideas about how to implement the above? Are there any other significant enhancements that people would like to see?