Analyse de l'usage de la RAM pour différentes opération

Nous allons ici réaliser un monitoring de la RAM pour différentes opérations différentes.

==> à mettre aussi dans le monitoring de la RAM...

Test sur un ESP 32 :

Au démarrage :

Juste après un reset, faire :

>>> print(gc.mem_free()) # libre
106912
>>> print(gc.mem_alloc()) # utilisee
6368
>>> print(gc.mem_free()+gc.mem_alloc()) # total
111168
>>> print(gc.mem_free()/(gc.mem_free()+gc.mem_alloc())) # % libre
0.9522164

95% de la freeRAM est libre au démarrage (6K utilisé), et on dispose de plus de 100K libre.

Import du programme de monitoring de la RAM :

Ce programme utilise une librairie pour gérer l'afficheur OLED, importe plusieurs classes du module machine, le module time et réalise l'affichage en temps réel sous forme graphique du niveau de RAM utilisée. Ce programme utilise un list de 128 éléments qui "rollent"

>>> gc.mem_free()
102384
>>> gc.mem_alloc()
8784
>>> print(gc.mem_free()/(gc.mem_free()+gc.mem_alloc()))
0.9208405
On a grosso modo 2.5Ko de plus d'utilisé en RAM ce qui est très peu en l'occurrence pour ce que fait ce programme.

Création d'une fonction simple

On définit la fonction suivante qui va nous servir par la suite :

import gc
lastMem=0
def memStat():
    global lastMem
    gc.collect()
    print ("free :"+ str(gc.mem_free()))
    print("used :"+ str(gc.mem_alloc()))
    print("% :"+str( gc.mem_free()/(gc.mem_free()+gc.mem_alloc())))
    print("delta : "+str(gc.mem_alloc()-lastMem ))
    lastMem=gc.mem_alloc()

On obtient :

>>> memStat()
free :101952
used :9280
% :0.9159471

Grosso modo 0.5Ko de plus.

Pour info, ici on caste les int en str dans la fonction print elle-même, ce qui utilise plus de RAM que d'utiliser format() à priori. Et d'autre part, l'utilisation de bytes est plus efficace que l'utilisation str

On prendra cela en compte lorsque la RAM restante sera critique.

Création d'un List

Si on crée un list de 1000 éléments, çà donne :

>>> x=list(range(1000))
>>> memStat()
free :97744
used :13488
% :0.8780945
delta : 4048

Soit 4Ko.

Noter que si on fait :

>>> x=None
>>> memStat()
free :101856
used :9376
% :0.9150835
delta : -4176

Il y a destruction de l'objet en RAM et libération en conséquence.

Noter que si on fait directement :

print(list(range(1000)))
>>> memStat()
free :101856
used :9376
% :0.9150835
delta : -64

Il n'y a pas dans ce cas d'allocation permanente. Il y a un pic d'utilisation qui disparaît dans la foulée.

Note

Il ne faut recourir à des variables que si c'est indispensable car cela fait allocation mémoire équivalente.

Création d'un List de grande taille

>>> x=list(range(5000))
>>> memStat()
free :69040
used :42192
% :0.6198906
delta : 32720

On a + 32K ce qui semble beaucoup comparativement à un list de 1000 qui donnait que 4K.

Noter que si on fait :

>>> x=[0]*5000
>>> memStat()
free :81808
used :29424
% :0.7347438
delta : 19952

On a +20K ce qui est plus cohérent.

De plus noter que si on fait :

>>> x=[0]*10000
>>> memStat()
free :61808
used :49424
% :0.5548359
delta : 39952

On a +40K et çà 'passe' alors que list(range(10 000)) ne passe pas.

On obtient un résultat comparable avec un list de lettres :

>>> x=['A']*10000
>>> memStat()
free :61808
used :49424
% :0.5548359
delta : 39952

Warning

Par contre, attention, on a un pic à plus du double lors de ces opérations qui doit correspondre à la manip de création par micropython.

Note

Retenir qu'avec un list de 10 000 nombres, on utilise 40K... çà va vite...