Header Ads

MicroPython Pyboard - Memoire disponible (taille d'un objet)

Jusque là, il y avait assez de mémoire sur ma Pyboard pour ne pas être trop tracassé.

Le projet de support ILI9431 (écran TFT SPI) est suffisamment excitant pour y investir du temps et produire des fonts complémentaires.
Le hic, c'est qu'une fois deux définitions de fonts + le pilote LCD chargés, la PyBoard se plein du manque de RAM.

Que faire en cas de problème de RAM?
Evaluer la taille de certains objets et envisager une optimisation/reécriture en vue de diminuer l'empreinte mémoire.

Comment évaluer la taille d'un objets?
Pour le moment, le mieux que j'ai trouvé c'est:
  1. Isoler l'objet en question dans un fichier séparé.
  2. Utiliser la bibliothèque "garbage collector" (ramasse miette) pour collecter l'empreinte mémoire (voir ci-dessous)
  3. Charger le fichier python en REPL avec l'instruction
    from fichier import mon_objet
  4. re-collecter l'empreinte mémoire avec le garbage collector et faire une soustraction
C'est empirique... mais cela permet de se faire une idée.

Cas pratique

>>> import gc
>>> class Foo:
...     def __init__(self):
...         self.bar = "123456"
...
>>> def test():
...     gc.collect()
...     before = gc.mem_free()
...     foo = Foo()
...     gc.collect()
...     after = gc.mem_free()
...     print("Foo object takes up", before - after, "bytes")
...
>>> test()
Foo object takes up 80 bytes

ATTENTION: Il faut faire le calcul à l'intérieur d'une fonction de sorte que vous n'avez pas de mémoire utilisée par le parser/compilateur, ce qui serait le cas s'il compilait les lignes depuis des saisies REPL (l'entrée en ligne de commande).

Qu'en conclure?
Le chargement de l'objet Arial_14 depuis /fonts/arial_14.py aura coûté pas moins de 101440 - 91888 = 9552 octets. Oufti 9 Ko!!

Du côté de l'allocation de mémoire l'on constate que l'on a alloué 10272 - 752 = 9520 octets (presque pareil).

Ce qui est intéressant, c'est que l'exécution du ramasse miette ( gc.collect() ou collect() ) la mémoire allouée redescend de 10272 octets à 6720 octets, on récupère donc environ 3552 octets... soit 3.5 Ko.

Ne nous méprenons pas, il s'agit probablement d'une partie de la mémoire utilisée par notre session REPL, et probablement pour le chargement et le parsing du fichier arial_14.py.

Quoi qu'il en soit, en cours de chargement, il faudra bien 10 Ko disponibles!

Addendum
Le forum MicroPython propose de mesure la différence de mémoire disponible avant et après la création. Avec l'exécution de "garbage collector" (ramasse miette) entre les deux:
>>> import gc
>>> class Foo:
...     def __init__(self):
...         self.bar = "123456"
...
>>> def test():
...     gc.collect()
...     before = gc.mem_free()
...     foo = Foo()
...     gc.collect()
...     after = gc.mem_free()
...     print("Foo object takes up", before - after, "bytes")
...
>>> test()
Foo object takes up 80 bytes

Autres tutoriels 
Venez découvrir nos autres tutoriels MicroPython sur le Wiki de mchobby.