parallaxinc / cyberbot

Firmware, library, and loader code for cyberbot hardware
MIT License
8 stars 0 forks source link

Examples -> Memory Errors #5

Open AndyLindsay opened 5 years ago

AndyLindsay commented 5 years ago

Examples that worked as-is with the 10/25 library get a memory error when updating to the 11/1 library. A temporary solution is to trim methods from the library that the example does not use.

AndyLindsay commented 5 years ago

BTW, this was with Mu set to minify.

MatzElectronics commented 5 years ago

Was the jsfiddle minifier used to compress the cyber:bot library? Im not having the same experience yet...

PropGit commented 5 years ago

@AndyLindsay tried the jsfiddle with me in a Hangout today. I think the micro:bit complained about a missing function. Maybe we could try this with you to see what we're doing differently?

MatzElectronics commented 5 years ago

Okay - I've been really picking at this memory thing tonight, and I'm starting to see a pattern, and hopefully from there some clues on how to both optimize it and write programs.

It appears that there is both a total character count restriction AND a restriction on variables (and definitions?) in memory - and the second one is actually the culprit in this case.

I'm going to optimize the .min file by hand for now - and it doesn't appear that we need to be compressing the examples themselves.

What DOES make a difference is adding variables where they aren't essential. For example:

    wheelL = kp * errorL
    wheelR = -kp * errorR

    bot(18).servo_speed(wheelL)
    bot(19).servo_speed(wheelR)

versus:

    bot(18).servo_speed(kp * errorL)
    bot(19).servo_speed(-kp * errorR)
MatzElectronics commented 5 years ago

@AndyLindsay, I have the example working with an improved version of the newest library. Give it a try again. Use the .min version in this repo, that should work well now.

AndyLindsay commented 5 years ago

No out-of-memory errors are apparent in current examples. They are all pretty concise. An IR Multi Bot example would be another better test. Navigation courses and dance routines also tend to be longer.

PropGit commented 5 years ago

This apparent limitation is very disturbing particularly because of what it may mean for users of our library... for example, are we taking away their ability to create another variable simply because we chose to use one more?

MatzElectronics commented 5 years ago

From Carlos @ micro:bit -

The user Python code itself is stored in flash together with the MicroPython runtime, the text is UTF-8encoded and written to a known location with a small header. If you are using the online editor there is a current limitation of 8KBs, but in the future we want to move towards using the MicroPython filesystem instead. This method can use for code all the flash space not claimed by the MicroPython runtime (which is about 20KBs at the moment).

For RAM there is 10KBs of heap available for the user Python code. Because the Python code is interpreted and executed by the run time, any allocations are stored in memory and later freed by the garbage collector when possible. I recommend this article from the upstream MicroPython docs, as it contains quite a few useful tips about memory: http://docs.micropython.org/en/v1.9.2/pyboard/reference/constrained.html

The micro:bit port of MicroPython includes the “gc” and “micropython” modules with useful functions to analyse the memory on run time, so I would recommend having a look at those as well, as it can help to give you a better sense of how memory is being used. An example running from the REPL:

MicroPython v1.9.2-34-gd64154c73 on 2017-09-01; micro:bit v1.0.0 with nRF51822
Type "help()" for more information.
>>> import gc, micropython
>>> micropython.mem_info(True)
stack: 524 out of 1800
GC: total: 10048, used: 560, free: 9488
No. of 1-blocks: 12, 2-blocks: 7, max blk sz: 3, max free sz: 562
GC memory layout; from 200001f0:
00000: h=BhBTBh=h=h=hhh==h=...hhhhh=......h==h=......................hh
00400: ==..............................................................
(7 lines all free)
02400: ....................................................
>>> gc.collect()
>>> micropython.mem_info()
stack: 516 out of 1800
GC: total: 10048, used: 432, free: 9616
No. of 1-blocks: 5, 2-blocks: 8, max blk sz: 3, max free sz: 579
>>> dir(gc)
['__name__', 'collect', 'disable', 'enable', 'isenabled', 'mem_free', 'mem_alloc', 'threshold']
>>> dir(micropython)
['__name__', 'const', 'opt_level', 'mem_info', 'qstr_info', 'stack_use', 'heap_lock', 'heap_unlock', 'kbd_intr']