gc.collect(): optimisation tas/heap Python 83 Premium CE 5.5
Posted: 20 May 2020, 17:16
Dans sa prochaine mise à jour 5.5 gratuite prévue pour Mai 2020, Texas Instruments va rajouter de formidables possibilités historiques à ta TI-83 Premium CE :
Python 5.5 offre de nouveaux modules intégrés pour tes scripts Python :
- mise à jour en 5.5 de l'application SciTools
- mise à jour en 5.5 de l'application Periodic
- mise à jour en 5.5 de l'application Python (TI-83 Premium CE Édition Python uniquement)
Python 5.5 offre de nouveaux modules intégrés pour tes scripts Python :
- time, certes déjà présent mais maintenant listé au menu et donc officiel
- ti_system, avec diverses possibilités :
- détection des simples pressions de touches clavier, y compris avec un clavier USB externe !
- affichage dans la console à la ligne que tu veux
- exportation de listes de nombres du contexte Python vers l'environnement de la calculatrice
- importation dans le contexte Python de listes existant dans l'environnement de la calculatrice vers
- et donc plus généralement un début d'intégration du Python à l'environnement mathématique de la calculatrice; plus besoin de traiter les tâches numériques à part, l'application Python 5.5 va enfin pouvoir servir s'articulier naturellement au sein de la résolution de problèmes et tâches complexes !
- ti_plotlib, une bibliothèque graphique pour tracer dans un repère othogonal, conformément aux programmes de Mathématiques et Physique-Chimie, comparable à matplotl chez Casio ou encore matplotlib.pyplot, et gérant ici les diagrammes suivants :
- nuage de points
- diagramme en ligne brisée
- droite de régression linéaire
- ti_graphics pour contrôler directement les pixels de l'écran, comparable à kandinsky chez NumWorks ou encore casioplot
- ti_hub, pour les projets d'objects connectés à l'aide de l'interface TI-Innovator Hub
- ti_rover, pour les projets de robotique à l'aide du TI-Innovator Rover
Sommaire :
1) mémoire de tas / heap et module gc
Go to topL'appel mem() avec le script mem.py suivant permet d'estimer la capacité du tas (heap) Python, et retournait jusqu'à présent près de 20K sur TI-83 Premium CE Édition Python :
Les formidables nouveautés de la version 5.5 semblent hélas avoir un coût important, à vide nous trouvons désormais à peine 17,5K de libres avec la version 5.5, un effondrement non négligeable de plus de 2,5K.
La TI-83 Premium CE Édition Python fait partie des très rares calculatrices à disposer du module gc (garbage collect), module qui va nous être bien pratique pour comprendre ce qui se passe. Retenons les appels suivants :
Testons à vide à l'aide du petit script suivant, sur l'ancienne et la nouvelle version :
Nous découvrons donc que le tas Python de la TI-83 Premium CE Édition Python a dans tous les cas une capacité totale de 19,968 Ko.
Ce n'est donc pas la capacité globale qui change mais la consommation du tas à vide, à peine plus de 600 o en version 5.4, et maintenant plus de 3 Ko en version 5.5. En effet lorsque tu lances tes scripts Python plusieurs choses sont initialisées et consomment du tas avant même l'exécution de ta première ligne de code. Et c'est là qu'il y a une lourde différence :
En passant il est normal ici de trouver un peu moins d'espace mémoire libre qu'avec le script précédent, vu qu'il le tas a subit une consommation supplémentaire à cause de l'imporation du module gc.
Tentons maintenant un appel explicite demandant de nettoyer la mémoire, avec
Et ben non, pas de chance ici, le nettoyage mémoire non seulement ne nous libère rien mais arriver même à consommer un petit peu. :troll
D'où le classement définitif en terme de capacité tas (heap) maximale utilisable pour tes scripts, avec la capacité totale précisée lorsque le module gc est disponible :
Mais attends nous n'avons pas encore dit notre dernier mot, passons aux modules importables et voyons ce que la fonction
- Code: Select all
def sizeenv():
s=0
import __main__
for o in dir(__main__):
try:s+=size(eval(o))
except:pass
return s
def size(o):
s,t=0,type(o)
if t==str:s=49+len(o)
if str(t)=="<class 'function'>":s=136
if t==int:
s=24
while o:
s+=4
o>>=30
if t==list:
s+=64
for so in o:s+=8+size(so)
return s
def mem(v=1,r=1):
try:
l=[]
try:
l+=[r and 793+sizeenv()]
if v*r:print(" ",l[0])
l+=[0]
l+=[""]
l[2]+="x"
while 1:
try:l[2]+=l[2][l[1]:]
except:
if l[1]<len(l[2])-1:l[1]=len(l[2])-1
else:raise(Exception)
except:
if v:print("+",size(l))
try:l[0]+=size(l)
except:pass
try:l[0]+=mem(v,0)
except:pass
return l[0]
except:return 0
Les formidables nouveautés de la version 5.5 semblent hélas avoir un coût important, à vide nous trouvons désormais à peine 17,5K de libres avec la version 5.5, un effondrement non négligeable de plus de 2,5K.
La TI-83 Premium CE Édition Python fait partie des très rares calculatrices à disposer du module gc (garbage collect), module qui va nous être bien pratique pour comprendre ce qui se passe. Retenons les appels suivants :
gc.mem_alloc()
retourne l'espace occupé sur le tas (heap)gc.mem_free()
retourne l'espace libre sur le tas (heap)gc.collect()
, formidable fonction qui nettoie / optimise le tas (heap)
Testons à vide à l'aide du petit script suivant, sur l'ancienne et la nouvelle version :
- Code: Select all
from gc import *
a, f = 0, 0
a, f = mem_alloc(), mem_free()
(a, f, a+f)
Nous découvrons donc que le tas Python de la TI-83 Premium CE Édition Python a dans tous les cas une capacité totale de 19,968 Ko.
Ce n'est donc pas la capacité globale qui change mais la consommation du tas à vide, à peine plus de 600 o en version 5.4, et maintenant plus de 3 Ko en version 5.5. En effet lorsque tu lances tes scripts Python plusieurs choses sont initialisées et consomment du tas avant même l'exécution de ta première ligne de code. Et c'est là qu'il y a une lourde différence :
En passant il est normal ici de trouver un peu moins d'espace mémoire libre qu'avec le script précédent, vu qu'il le tas a subit une consommation supplémentaire à cause de l'imporation du module gc.
Tentons maintenant un appel explicite demandant de nettoyer la mémoire, avec
gc.collect()
.Et ben non, pas de chance ici, le nettoyage mémoire non seulement ne nous libère rien mais arriver même à consommer un petit peu. :troll
D'où le classement définitif en terme de capacité tas (heap) maximale utilisable pour tes scripts, avec la capacité totale précisée lorsque le module gc est disponible :
- 1,032942 Mo : Casio Graph 90+E
- 1,022145 / 1,024512 Mo : HP Prime G1 (version alpha)
- 100,560 Ko : Casio Graph 35+E II
- 32,339 Ko : NumWorks (firmware Omega)
- 31,624 Ko : NumWorks
19,500 / 19,968 Ko : TI-83 Premium CE Édition Python(ancienne version)- 17,359 / 19,968 Ko : TI-83 Premium CE Édition Python (nouvelle version)
- 2,049276 Mo : TI-Nspire (application MicroPython)
- 1,032942 Mo : Casio Graph 90+E / fx-CG50
- 1,022145 Mo : HP Prime G1 (version alpha)
- 257,636 / 258,048 Ko : Casio Graph 35+E / 75+ / 35+ USB Power Graphic 2 / 75/95 USB Power Graphic 2 / fx-9750/9860GII USB Power Graphic 2
- 100,560 Ko : Casio Graph 35+E II / fx-9750/9860GIII
- 32,339 Ko : NumWorks (firmware Omega)
- 31,624 Ko : NumWorks
- 31,520 / 32,256 Ko : Casio Graph 35+E II / 85 / 35+ USB Power Graphic 1 / 75/95 USB Power Graphic 1 / fx-9750/9860GIII / fx-9750/9860GII USB Power Graphic 1 / fx-9860G
- 22,605 / 22,912 Ko : TI-83 Premium CE + TI-Python (firmware tiers)
- 19,500 / 19,968 Ko : TI-83 Premium CE + TI-Python +
TI-83 Premium CE Édition Python(ancienne version) - 17,359 / 19,968 Ko : TI-83 Premium CE Édition Python (nouvelle version)
La TI-83 Premium CE Édition Python était déjà la pire solution Python pour la capacité tas, et cela ne fait donc qu'empirer.
C'est probablement largement suffisant pour les petits algo-musements de quelques lignes qui seront traités en Mathématiques ou Physique-Chimie.
Le problème est ailleurs, ceux qui auront suffisamment accroché pour avoir envie d'aller plus loin risquent d'être rapidement déçus par leur calculatrice...
Ceux qui aborderont des projets (SNT, NSI, ... ou même non scolaires) risquent d'obtenir des erreurs de mémoire assez rapidement après le début du projet...
Car le Python ce n'est pas du C, les objets Python les plus élémentaires sont extrêmement gourmands en mémoire :
C'est probablement largement suffisant pour les petits algo-musements de quelques lignes qui seront traités en Mathématiques ou Physique-Chimie.
Le problème est ailleurs, ceux qui auront suffisamment accroché pour avoir envie d'aller plus loin risquent d'être rapidement déçus par leur calculatrice...
Ceux qui aborderont des projets (SNT, NSI, ... ou même non scolaires) risquent d'obtenir des erreurs de mémoire assez rapidement après le début du projet...
Car le Python ce n'est pas du C, les objets Python les plus élémentaires sont extrêmement gourmands en mémoire :
- 64 octets rien que pour une liste vide
- plus 8 octets pour chaque élément de liste supplémentaire, sans compter la taille de l'élément en question
- 24 octets pour un entier nul
- 28 octets pour un entier court non nul
- 49 octets rien que pour une chaîne vide
- plus 1 octet par caractère de chaîne supplémentaire
- ...
Mais attends nous n'avons pas encore dit notre dernier mot, passons aux modules importables et voyons ce que la fonction
gc.collect()
peut bien donner dessus. 2) importations modules et consommation tas / heap
Go to topVoyons maintenant un petit peu ce que consomme l'importation de chaque module disponible sur le tas (heap), grâce ici aux formidables possibiltés exclusives du module gc.
Il suffit d'appeler les fonctions du module gc vues plus haut, juste avant et après l'importation d'un module, afin de vérifier l'espace consommé sur le tas. Nous allons même tenter en prime un nettoyage du tas après importation, et voir si cela améliore les choses.
Voici un script en ce sens, volontairement minimaliste sans définition de fonction afin de minimiser les chances de déclencher un nettoyage mémoire en dehors des appels explicites à
Voici donc les consommations de tas à l'importation puis après nettoyage des différents modules intégrés :
Il suffit d'appeler les fonctions du module gc vues plus haut, juste avant et après l'importation d'un module, afin de vérifier l'espace consommé sur le tas. Nous allons même tenter en prime un nettoyage du tas après importation, et voir si cela améliore les choses.
Voici un script en ce sens, volontairement minimaliste sans définition de fonction afin de minimiser les chances de déclencher un nettoyage mémoire en dehors des appels explicites à
gc.collect()
:- Code: Select all
from gc import mem_free, collect
smod = input('Module : ')
mf1, mf2, mf3 = 0, 0, 0
scmd = 'from ' + smod + ' import *'
collect()
mf1 = mem_free()
exec(scmd)
mf2 = mem_free()
collect()
mf3 = mem_free()
print("initial: ", mf1)
print("importation: ", mf2, mf2-mf1)
print("nettoyage: ", mf3, mf3-mf1)
Voici donc les consommations de tas à l'importation puis après nettoyage des différents modules intégrés :
- builtins : 800 o à l'importation, 720 o après nettoyage
- array : 96 o à l'importation, 16 o après nettoyage
- collections : 96 o à l'importation, 16 o après nettoyage
- gc : 112 o à l'importation, 32 o après nettoyage (mesure possiblement faussée, puisque le module est déjà partiellement importé)
- math : 320 o à l'importation, 240 o après nettoyage
- random : 160 o à l'importation, 80 o après nettoyage
- sys : 208 o à l'importation, 128 o après nettoyage
- time : 112 o à l'importation, 32 o après nettoyage
- ti_graphics : 2,880 Ko à l'importation, 1,584 Ko après nettoyage
- ti_hub : 256 o à l'importation, 176 o après nettoyage
- ti_plotlib : 7,216 Ko à l'importation, 3,504 Ko après nettoyage
- ti_rover : 4,832 Ko à l'importation, 2,352 Ko après nettoyage
- ti_system : 208 o à l'importation, 128 o après nettoyage
- ce_box : 13,440 Ko à l'importation, 6,704 Ko après nettoyage
- ce_chart : 13,328 Ko à l'importation, 6,448 Ko après nettoyage
- ce_quivr : 8,832 Ko à l'importation, 3,904 Ko après nettoyage
- ce_turtl : 9,792 Ko à l'importation, 4,944 Ko après nettoyage
Et oui, c'est fantastique, l'appel
ti_graphics, ti_plotlib, ti_rover, ce_box, ce_chart, ce_quivr et ce_turtl, la consommation énorme de chacun de ces modules à l'importation est immédiatement quasiment réduite de moitié !
gc.collect()
à ce jour exclusif sur TI-83 Premium CE Edition Pyton te permet de libérer du tas, et ce de façon très significative dans le contexte de l'utilisation des plus gros modules dont certains te remplissaient quasiment tout les tas ! ti_graphics, ti_plotlib, ti_rover, ce_box, ce_chart, ce_quivr et ce_turtl, la consommation énorme de chacun de ces modules à l'importation est immédiatement quasiment réduite de moitié !