Introduction
La gestion de la mémoire est le processus d’allocation, de désallocation et de coordination efficaces de la mémoire afin que tous les différents processus se déroulent sans problème et puissent accéder de manière optimale aux différentes ressources du système. La gestion de la mémoire implique également le nettoyage de la mémoire des objets auxquels on n’accède plus.
Dans Python, le gestionnaire de mémoire est responsable de ce genre de tâches en s’exécutant périodiquement pour nettoyer, allouer et gérer la mémoire. Contrairement à C, Java et d’autres langages de programmation, Python gère les objets en utilisant le comptage de références. Cela signifie que le gestionnaire de mémoire garde la trace du nombre de références à chaque objet dans le programme. Lorsque le nombre de références d’un objet tombe à zéro, ce qui signifie que l’objet n’est plus utilisé, le ramasseur d’ordures (qui fait partie du gestionnaire de mémoire) libère automatiquement la mémoire de cet objet particulier.
L’utilisateur n’a pas à se soucier de la gestion de la mémoire car le processus d’allocation et de désallocation de la mémoire est entièrement automatique. La mémoire récupérée peut être utilisée par d’autres objets.
Python Garbage Collection
Comme expliqué précédemment, Python supprime les objets qui ne sont plus référencés dans le programme afin de libérer de l’espace mémoire. Ce processus par lequel Python libère les blocs de mémoire qui ne sont plus utilisés est appelé Garbage Collection. Le Garbage Collector (GC) de Python fonctionne pendant l’exécution du programme et est déclenché si le nombre de références tombe à zéro. Le nombre de références augmente si un objet se voit attribuer un nouveau nom ou est placé dans un conteneur, comme un tuple ou un dictionnaire. De même, le nombre de références diminue lorsque la référence à un objet est réaffectée, lorsque la référence de l’objet sort de sa portée ou lorsqu’un objet est supprimé.
La mémoire est un tas qui contient des objets et d’autres structures de données utilisées dans le programme. L’allocation et la désallocation de cet espace de tas sont contrôlées par le gestionnaire de mémoire Python par l’utilisation de fonctions API.
Objets Python en mémoire
Chaque variable dans Python agit comme un objet. Les objets peuvent être simples (contenant des nombres, des chaînes de caractères, etc.) ou des conteneurs (dictionnaires, listes ou classes définies par l’utilisateur). En outre, Python est un langage dynamiquement typé, ce qui signifie que nous n’avons pas besoin de déclarer les variables ou leurs types avant de les utiliser dans un programme.
Par exemple :
Si vous regardez les 2 premières lignes du programme ci-dessus, l’objet x
est connu. Lorsque nous supprimons l’objet x
et essayons de l’utiliser, nous obtenons une erreur indiquant que la variable x
n’est pas définie.
Vous pouvez voir que le garbage collector en Python est entièrement automatisé et que le programmeur n’a pas besoin de s’en préoccuper, contrairement à des langages comme le C.
Modification du garbage collector
Le garbage collector Python a trois générations dans lesquelles les objets sont classés. Un nouvel objet au point de départ de son cycle de vie constitue la première génération du garbage collector. Au fur et à mesure que l’objet survit au ramasse-miettes, il passe à la génération suivante. Chacune des 3 générations du ramasseur d’ordures a un seuil. Plus précisément, lorsque le seuil du nombre d’allocations moins le nombre de dé0allocations est dépassé, cette génération lance la collecte des ordures.
Les générations plus anciennes sont également collectées plus souvent que les générations supérieures. Cela est dû au fait que les objets les plus récents sont plus susceptibles d’être jetés que les anciens.
Le module gc
comprend des fonctions permettant de modifier la valeur seuil, de déclencher manuellement un processus de garbage collection, de désactiver le processus de garbage collection, etc. Nous pouvons vérifier les valeurs de seuil des différentes générations du garbage collector en utilisant la méthode get_threshold()
:
import gcprint(gc.get_threshold())
Sample Output:
(700, 10, 10)
Comme vous le voyez, ici nous avons un seuil de 700 pour la première génération, et 10 pour chacune des deux autres générations.
Nous pouvons modifier la valeur du seuil pour déclencher le processus de collecte des ordures en utilisant la méthode set_threshold()
du module gc
:
gc.set_threshold(900, 15, 15)
Dans l’exemple ci-dessus, nous avons augmenté la valeur du seuil pour les 3 générations. L’augmentation de la valeur seuil va diminuer la fréquence d’exécution du garbage collector. Normalement, nous ne devons pas trop penser au garbage collector de Python en tant que développeur, mais cela peut être utile lors de l’optimisation du runtime Python pour votre système cible. L’un des principaux avantages est que le mécanisme de garbage collection de Python gère automatiquement de nombreux détails de bas niveau pour le développeur.
Pourquoi effectuer un garbage collection manuel?
Nous savons que l’interpréteur Python garde une trace des références aux objets utilisés dans un programme. Dans les versions antérieures de Python (jusqu’à la version 1.6), l’interpréteur Python utilisait uniquement le mécanisme de comptage des références pour gérer la mémoire. Lorsque le nombre de références tombe à zéro, l’interpréteur Python libère automatiquement la mémoire. Ce mécanisme classique de comptage de références est très efficace, sauf qu’il ne fonctionne pas lorsque le programme comporte des cycles de référence. Un cycle de référence se produit si un ou plusieurs objets sont référencés les uns aux autres, et donc le compte de référence n’atteint jamais zéro.
Prenons un exemple.
>>> def create_cycle():... list = ... list.append(list)... return list... >>> create_cycle()]
Le code ci-dessus crée un cycle de référence, où l’objet list
se réfère à lui-même. Par conséquent, la mémoire de l’objet list
ne sera pas libérée automatiquement lorsque la fonction revient. Le problème du cycle de référence ne peut pas être résolu par le comptage de référence. Cependant, ce problème de cycle de référence peut être résolu en modifiant le comportement du garbage collector dans votre application Python.
Pour ce faire, nous pouvons utiliser la fonction gc.collect()
du module gc
.
import gcn = gc.collect()print("Number of unreachable objects collected by GC:", n)
La gc.collect()
renvoie le nombre d’objets qu’elle a collectés et désalloués.
Il existe deux façons d’effectuer la collecte manuelle des déchets : la collecte basée sur le temps ou la collecte basée sur les événements.
La collecte basée sur le temps est assez simple : la fonction gc.collect()
est appelée après un intervalle de temps fixe.
La collecte de déchets basée sur les événements appelle la fonction gc.collect()
après qu’un événement se soit produit (c’est-à-dire lorsque l’application est quittée ou que l’application reste inactive pendant une période de temps spécifique).
Comprenons le travail de collecte de déchets manuelle en créant quelques cycles de référence.
La sortie est la suivante :
Creating garbage...Collecting...Number of unreachable objects collected by GC: 8Uncollectable garbage:
Le script ci-dessus crée un objet liste qui est référencé par une variable, nommée de manière créative list
. Le premier élément de l’objet liste se réfère à lui-même. Le nombre de références de l’objet liste est toujours supérieur à zéro, même s’il est supprimé ou hors de portée dans le programme. Par conséquent, l’objet list
n’est pas ramassé en raison de la référence circulaire. Le mécanisme de garbage collector de Python vérifiera automatiquement et collectera périodiquement les références circulaires.
Dans le code ci-dessus, comme le nombre de références est au moins égal à 1 et ne peut jamais atteindre 0, nous avons forcé le garbage collector des objets en appelant gc.collect()
. Cependant, n’oubliez pas de ne pas forcer la collecte des ordures fréquemment. La raison en est que même après avoir libéré la mémoire, la GC prend du temps pour évaluer l’éligibilité de l’objet à être garbage collecté, ce qui prend du temps processeur et des ressources. De plus, n’oubliez pas de gérer manuellement le garbage collector uniquement après le démarrage complet de votre application.
Conclusion
Dans cet article, nous avons discuté de la façon dont la gestion de la mémoire en Python est gérée automatiquement en utilisant des stratégies de comptage de références et de garbage collection. Sans garbage collection, la mise en œuvre d’un mécanisme de gestion de la mémoire réussi en Python est impossible. De plus, les programmeurs ne doivent pas s’inquiéter de la suppression de la mémoire allouée, car le gestionnaire de mémoire de Python s’en charge. Cela conduit à moins de fuites de mémoire et à de meilleures performances.