-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
mpremote: Support bytecode raw paste for 'mpremote run module.mpy' #8744
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
mpremote: Support bytecode raw paste for 'mpremote run module.mpy' #8744
Conversation
@jimmo @andrewleech @dpgeorge Do you folks have any suggestions about this? |
I think @andrewleech had an idea (and maybe somewhere in a PR) to build .mpy files on the fly in mpremote (calling out to mpy-cross). That would fit well here. |
Codecov Report
@@ Coverage Diff @@
## master #8744 +/- ##
==========================================
- Coverage 98.31% 98.31% -0.01%
==========================================
Files 155 156 +1
Lines 20304 20326 +22
==========================================
+ Hits 19962 19983 +21
- Misses 342 343 +1
Continue to review full report at Codecov.
|
I've got an open draft MR which adds support for manifest files to mpremote - with this any python files referenced in a manifest.py are bytecompiled into a local folder with mpy-cross, exposed via mount, then added to sys.path so that the device can easily import everything. So this would reduce ram use and increase import speed (less data to transfer) but still requires mount. These changes wouldn't need any new support within micropython either, but don't address all of your needs - specifically directly running an mpy file without mount support. Would it be feasible to include vfs support in a build without any specific filesystem libraries? That way mount could be used without needing the bulk of any one of the fs formats. That being said, while I haven't looked at your code in detail I presume a raw paste mode can be added with less code than the VFS framework. I haven't looked into the ram buffer size needs while importing a mpy file over mount but expect that bytecode would be read "line by line" so to speak by the vm? I don't know if it buffers the entire mpy file in ram when running from a (mount) filesystem? |
That sounds awesome. Well worth doing! A problem could occur with "incompatible mpy format" messages. Would it be possible to check the firmware version on the target against the cross-compiler version? A mismatch could prevent pre-compilation and issue a warning. |
a933f69
to
717a1bd
Compare
717a1bd
to
249cb20
Compare
- Adds a new raw paste command 'B' for 'raw paste bytecode' ('A' is 'paste source') - Adds an escaping mechanism (Ctrl-F <char + 8>) during raw paste so bytes less than 8 can be sent without triggering Ctrl-C or Ctrl-D handlers. The two-byte escape sequence still counts as one byte in the paste window. - Adds relevant support to mpremote.py Signed-off-by: Angus Gratton <gus@projectgus.com>
Signed-off-by: Angus Gratton <gus@projectgus.com>
Signed-off-by: Angus Gratton <gus@projectgus.com>
The raw repl language is gradually getting more complex. To structure the code a bit more, introduce some names for the different control characters and the "init command" sequence which is currently only used for starting a paste. Signed-off-by: Angus Gratton <gus@projectgus.com>
249cb20
to
02826f0
Compare
Hi @andrewleech, Sorry I didn't reply to these earlier on:
This is a good question! Actually the target I'm focusing on, B_L072Z_LRWAN1 (32KB RAM), has the necessary base vfs support, but on master it runs out of memory when With this change and a hacky patch to pre-compile the _fs_hook_code on top then I can do
Compared to a plain REPL:
So I'm thinking "mpremote mount" may not ever be viable on these very small systems.
Honestly I don't fully understand this yet, I'm going to take another look through it soon. |
My reading of persistentcode.c is that it reads all of the byte code into memory before it executes. This seems probably necessary to keep complexity down as the bytecode may contain jumps, calls to child scopes, etc. that don't happen linearly. One interesting thing I noticed is that the "outer scope" of bytecode (i.e. the code which is executed as the module imports) is kept in memory after the execution/import completes (for any call that goes via Downside, in most cases freeing this won't save a lot - for example in @dpgeorge @jimmo Does that sound right, or am I missing something? |
Use specific pid for Flipper Wifi
This is an automated heads-up that we've just merged a Pull Request See #13763 A search suggests this PR might apply the STATIC macro to some C code. If it Although this is an automated message, feel free to @-reply to me directly if |
For resource constrained devices without
mpremote mount
support, it is useful to be able to directly run precompiled bytecode (mpremote run
) when developing, rather having to send source code each time.Currently this is possible using pyboard.py - the implementation loads some loader Python and injects the bytecode as a variable. This approach reduces RAM usage further by using the "raw paste" window to paste into the same code path that loads and executes .mpy files (thanks Damien for this tip).
Summary of changes
<char>
is escaped asCtrl-F
<char + 8>
) during raw paste so byte values less than 8 can be sent without triggering Ctrl-C or Ctrl-D handlers. The two-byte escape sequence still counts as one byte in the paste window.Impact
Building for PYBV11 with default settings, .text segment +128 bytes.
TODOs
My understanding might be wrong, but this still currently streams the entire module into a memory buffer (mp_raw_code_load, mp_make_function_from_raw_code) and then executes it ( mp_call_function_0). Maybe this can be made to execute it in chunks as each Python statement completes, meaning less RAM usage for modules which execute some statements on import and don't need to keep those around. But I'm very new to this and haven't dug right into it, could be way off.(I think the soft reset before run makes this a bit of a moot point, although there are still potential savings for 'run'-ing a bytecode that doesn't define any code.)Test this works with(Seems only JavaScript port uses this method, at least by default, and it doesn't support mpremote - if I should test this on a different port, let me know.)MICROPY_REPL_EVENT_DRIVEN
Compatibility
I believe this approach is compatible between different mpremote.py and MicroPython versions:
Except for the case of anyone who was sending a raw Ctrl-F character as-is in a raw paste, in which case that will stop working as expected if the mprempote.py + firmware versions don't match (due to the Ctrl-F escape handler).