Repository navigation
Feat/type checking - #19742
Draft
Josverl wants to merge 6 commits into
Draft
Feat/type checking#19742Josverl wants to merge 6 commits into
Josverl wants to merge 6 commits into
Conversation
Used in Build: tools/ci.sh tools/boardgen.py tools/makemanifest.py tools/manifestfile.py tools/mpy-tool.py tools/insert-usb-ids.py tools/mpy_ld.py tools/uf2conv.py tools/uf2families.json tools/file2h.py tools/ar_util.py tools/dfu.py Used in Tests: tools/pyboard.py Used in build docs: tools/gen-cpydiff.py Signed-off-by: Jos Verlinde <[email protected]>
Signed-off-by: Jos Verlinde <[email protected]>
This uses the YAML anchors and aliases feature to re-use the same set of paths for both the push and pull_request triggers. Signed-off-by: Jos Verlinde <[email protected]>
Treat TYPE_CHECKING as a MicroPython const() to allow the code folding mechanism to remove code guarded by ``if TYPE_CHECKING:`` from the bytecode. Signed-off-by: Jos Verlinde <[email protected]>
Signed-off-by: Jos Verlinde <[email protected]>
Signed-off-by: Jos Verlinde <[email protected]>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #19742 +/- ##
=======================================
Coverage 98.55% 98.55%
=======================================
Files 182 182
Lines 23335 23354 +19
Branches 5 5
=======================================
+ Hits 22998 23017 +19
Misses 336 336
Partials 1 1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Code size report: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Special cases the parser's handling of
TYPE_CHECKING.It treats an assignment of exactly
TYPE_CHECKING = Falseas an private constant that canbe further optimised (out) by the compiler. It is treated similar to
_TYPE_CHECKING = const(False).This allows code that is only needed by static type checkers, such as imports
from
typingor method stubs, to be added without any runtime or code sizeoverhead, because code guarded by
if TYPE_CHECKING:is removed from thebytecode::
Static type checkers always treat
TYPE_CHECKINGasTrue, so they stillsee the guarded code. As with other module-private constants, no
TYPE_CHECKINGglobal variable is created. Only the bare name is recognised:from typing import TYPE_CHECKINGandtyping.TYPE_CHECKINGare notoptimised.
A
.mpybuilt with the feature contains no qstrs for the guarded names at all.Importing a
.pyfile saves less heap than importing a pre-compiled.mpy. The lexer still internsevery name in the file, guarded or not, so those qstrs are still allocated; only bytecode and global-dict space is
saved.
closes: #19734
Testing
I created a few sample modules to test the optimisation and to measure the impact.
(Currently these are not part of the PR, but can be shared)
Four sample modules use the pattern. Each was compiled as written ("after") and with
TYPE_CHECKINGrenamed toTYPE_CHECKINX("before"). The rename keeps the name length identicaland turns the optimisation off, so "before" matches the old behaviour exactly.
s1_mintypingnames +framebuffunction annotated with aCallables2_typicaltypingnames +typing_extensions.TypeAlias+ a guarded type alias definitions3_class_stubs@overloadstubs + the real method (SSD1306 style)s4_multiResults
.mpysizes are the flash or filesystem space taken by the deployed module. Heap saved is measuredafter import on the 64-bit unix port, in 32-byte GC blocks, so those numbers are coarse.
.mpybefore.py/.mpy)s1_mins2_typicals3_class_stubss4_multiFor comparison,
s1_minwith the three guard lines deleted compiles to 120 bytes, so the guard so the guardcosts only 1 byte of line-number info.
That growth is possibly caused by included debug line numbers that were pushed into the double-digit range (not verified)
Trade-offs and Alternatives
The trade off is adding code to the firmware , with the intent to reduce the overall firmware size
Additions:
This is to be offset by the zero-overhead addition of one or more frozen MicroPython modules that can use type annotations.
An initial rough test estimates the saving per mpy-cross compiled module at 64 - 400 bytes for pre-compiled .mpy modules, depending on the use of type annotations.
This would indicate that the feature saves firmware (and memory) if one or more frozen python modules use TYPE_CHECKING guards.
Should this be mpy-cross only ?
It is possible to only include this optimisation in mpy-cross, to avoid any impact on firmware size.
Benefits of mpy-cross only:
Against mpy-cross only:
Generative AI
I did not use generative AI tools when creating this PR.
I used generative AI tools when creating this PR, but a human has checked the
code and is responsible for the code and the description above.