Skip to content

Optimize import mechanism#30

Merged
romanz merged 4 commits into
trezor-v1.19.1from
romanz/2606/opt-imports
Jun 19, 2026
Merged

Optimize import mechanism#30
romanz merged 4 commits into
trezor-v1.19.1from
romanz/2606/opt-imports

Conversation

@romanz

@romanz romanz commented Jun 16, 2026

Copy link
Copy Markdown

Following trezor/trezor-firmware#7097.

The optimization is done in f5ec033 (micropython#11456, released in MicroPython 1.21), the first 3 commits are cherry-picked to avoid merge conflicts.

nomis and others added 4 commits June 16, 2026 12:11
There are two calls to mp_builtin___import__():
1. ports/unix/main.c:main_() which provides a str in args[0]
2. py/runtime.c:mp_import_name() which provides a qstr in args[0]

The default implementation of mp_builtin___import__() is
mp_builtin___import___default() which has a different implementation based
on MICROPY_ENABLE_EXTERNAL_IMPORT.

If MICROPY_ENABLE_EXTERNAL_IMPORT is disabled then the handling of weak
links assumes that args[0] is a `const char *`, when it is either a str or
qstr object.

Use the existing qstr of the module name instead, and also use a vstr
instead of strcpy() to ensure no overflow occurs.

(cherry picked from commit f8b0ae3)
This allows ports to override mp_builtin___import__.

This can be useful in MicroPython applications where
MICROPY_ENABLE_EXTERNAL_IMPORT has to be disabled due to its impact on
build size (2% to 2.5% of the minimal port). By overriding the otherwise
very minimal mp_builtin___import__, ports can still allow limited forms
of application-specific imports.

Signed-off-by: Laurens Valk <laurens@pybricks.com>
(cherry picked from commit d8ad878)
If sys.path is enabled, but empty, this will now no longer search the
filesystem. Previously an empty sys.path was equivalent to having
`sys.path=[""]`. This is a breaking change, but this behavior now matches
CPython.

This also provides an alternative mechanism to the u-prefix to force an
import of a builtin module:

```
import sys
_path = sys.path[:]
sys.path.clear()
import foo  # Forces the built-in foo.
sys.path.extend(_path)
del _path
```

Code size diff is -32 bytes on PYBV11.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
(cherry picked from commit 42f3f66)
This makes it so that sub-packages are resolved relative to their parent's
`__path__`, rather than re-resolving each parent's filesystem path.

The previous behavior was that `import foo.bar` would first re-search
`sys.path` for `foo`, then use the resulting path to find `bar`.

For already-loaded and u-prefixed modules, because we no longer need to
build the path from level to level, we no longer unnecessarily search
the filesystem. This should improve startup time.

Explicitly makes the resolving process clear:
 - Loaded modules are returned immediately without touching the filesystem.
 - Exact-match of builtins are also returned immediately.
 - Then the filesystem search happens.
 - If that fails, then the weak-link handling is applied.

This maintains the existing behavior: if a user writes `import time` they
will get time.py if it exits, otherwise the built-in utime. Whereas `import
utime` will always return the built-in.

This also fixes a regression from a7fa18c
where we search the filesystem for built-ins. It is now only possible to
override u-prefixed builtins. This will remove a lot of filesystem stats
at startup, as micropython-specific modules (e.g. `pyb`) will no longer
attempt to look at the filesystem.

Added several improvements to the comments and some minor renaming and
refactoring to make it clearer how the import mechanism works. Overall
code size diff is +56 bytes on STM32.

This work was funded through GitHub Sponsors.

Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
(cherry picked from commit 5255577)

@mmilata mmilata left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upstream has lots of further changes in builtinimport.c but no commit seems to be a bugfix for anything introduced here so all good.

@romanz

romanz commented Jun 19, 2026

Copy link
Copy Markdown
Author

Tested on all HW models -> trezor/trezor-firmware#7114 (comment)

@romanz romanz merged commit f5ec033 into trezor-v1.19.1 Jun 19, 2026
16 of 75 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants