Optymalizacje

MicroPython stosuje kilka optymalizacji, aby oszczędzać pamięć RAM, a także zapewnić wydajne wykonywanie programów. Ten rozdział omawia niektóre z tych optymalizacji.

Informacja

Internowanie łańcuchów znaków w MicroPython i Mapy i słowniki szczegółowo opisują inne optymalizacje dotyczące łańcuchów znaków i słowników.

Zamrożony kod bajtowy

Kiedy MicroPython ładuje kod Pythona z systemu plików, najpierw musi sparsować plik do tymczasowej reprezentacji w pamięci, a następnie wygenerować kod bajtowy do wykonania, przy czym oba te elementy są przechowywane na stercie (w pamięci RAM). Może to prowadzić do zużycia znacznych ilości pamięci. Kompilator krzyżowy MicroPython można wykorzystać do wygenerowania pliku .mpy zawierającego prekompilowany kod bajtowy dla modułu Pythona. Nadal będzie on ładowany do pamięci RAM, ale pozwala uniknąć dodatkowego narzutu związanego z etapem parsowania.

Jako dalszą optymalizację prekompilowany kod bajtowy z pliku .mpy może zostać „zamrożony” w obrazie oprogramowania układowego w ramach głównego procesu kompilacji oprogramowania układowego, co oznacza, że kod bajtowy będzie wykonywany z pamięci ROM. Może to prowadzić do znacznych oszczędności pamięci oraz zmniejszyć fragmentację sterty.

Więcej informacji znajduje się w Pliki manifestu MicroPython.

Zmienne

MicroPython przetwarza zmienne lokalne i globalne w różny sposób. Zmienne globalne są przechowywane i wyszukiwane w globalnym słowniku, który jest alokowany na stercie (należy zauważyć, że każdy moduł ma swój własny, oddzielny słownik, a więc oddzielną przestrzeń nazw). Z kolei zmienne lokalne są przechowywane na stosie wartości Pythona, który może znajdować się na stosie C lub na stercie. Dostęp do nich uzyskuje się bezpośrednio poprzez ich przesunięcie w obrębie stosu Pythona, co jest wydajniejsze niż globalne wyszukiwanie w słowniku.

Długość nazw zmiennych globalnych również wpływa na ilość zużywanej pamięci RAM, ponieważ identyfikatory są przechowywane w pamięci RAM. Im krótszy identyfikator, tym mniej zużywanej pamięci.

Inny aspekt jest taki, że zmienne const zaczynające się od podkreślenia są traktowane jako właściwe stałe i nie są alokowane ani dodawane do słownika, co pozwala zaoszczędzić nieco pamięci. Te zmienne używają const() z biblioteki MicroPython. Dlatego:

from micropython import const

X = const(1)
_Y = const(2)
foo(X, _Y)

Kompiluje się do:

X = 1
foo(1, 2)

Alokacja pamięci

Większość typowych konstrukcji MicroPython nie jest alokowana na stercie. Jednak następujące są:

  • Dynamiczne struktury danych, takie jak listy, mapowania itp.;

  • Funkcje, klasy i instancje obiektów;

  • importy; oraz

  • Pierwsze przypisanie zmiennych globalnych (w celu utworzenia slotu w słowniku globalnym).

Szczegółowe omówienie optymalizacji z perspektywy bardziej zorientowanej na użytkownika znajduje się w Maximising MicroPython speed.