Je me suis récemment intéressé aux algorithmes et j'ai commencé à les explorer en écrivant une implémentation naïve, puis en l'optimisant de diverses manières.
Je connais déjà le module Python standard pour le profil d'exécution (pour la plupart des choses, j'ai trouvé que la fonction magique timeit dans IPython était suffisante), mais je suis également intéressé par l'utilisation de la mémoire afin que je puisse également explorer ces compromis ( par exemple, le coût de la mise en cache d'une table de valeurs précédemment calculées par rapport à leur recalcul si nécessaire). Existe-t-il un module qui profilera l'utilisation de la mémoire d'une fonction donnée pour moi?
Réponses:
Celui-ci a déjà été répondu ici: Profileur de mémoire Python
Fondamentalement, vous faites quelque chose comme ça (cité de Guppy-PE ):
la source
Python 3.4 comprend un nouveau module:
tracemalloc
. Il fournit des statistiques détaillées sur le code qui alloue le plus de mémoire. Voici un exemple qui affiche les trois premières lignes allouant de la mémoire.Et voici les résultats:
Quand une fuite de mémoire n'est-elle pas une fuite?
Cet exemple est excellent lorsque la mémoire est toujours conservée à la fin du calcul, mais parfois vous avez du code qui alloue beaucoup de mémoire, puis libère tout cela. Ce n'est pas techniquement une fuite de mémoire, mais cela utilise plus de mémoire que vous ne le pensez. Comment pouvez-vous suivre l'utilisation de la mémoire lorsque tout est libéré? Si c'est votre code, vous pouvez probablement ajouter du code de débogage pour prendre des instantanés pendant son exécution. Sinon, vous pouvez démarrer un thread d'arrière-plan pour surveiller l'utilisation de la mémoire pendant l'exécution du thread principal.
Voici l'exemple précédent où le code a tous été déplacé dans la
count_prefixes()
fonction. Lorsque cette fonction revient, toute la mémoire est libérée. J'ai également ajouté quelquessleep()
appels pour simuler un calcul à long terme.Lorsque j'exécute cette version, l'utilisation de la mémoire est passée de 6 Mo à 4 Ko, car la fonction a libéré toute sa mémoire lorsqu'elle a terminé.
Voici maintenant une version inspirée d' une autre réponse qui démarre un deuxième thread pour surveiller l'utilisation de la mémoire.
Le
resource
module vous permet de vérifier l'utilisation actuelle de la mémoire et d'enregistrer l'instantané de l'utilisation maximale de la mémoire. La file d'attente permet au thread principal d'indiquer au thread du moniteur de mémoire quand imprimer son rapport et l'arrêter. Lorsqu'il s'exécute, il affiche la mémoire utilisée par l'list()
appel:Si vous êtes sous Linux, vous trouverez peut-être
/proc/self/statm
plus utile que leresource
module.la source
long_running()
à l'intérieur de lacount_prefixes()
fonction, les valeurs RSS maximales ne seront pas imprimées avant lelong_running()
retour. Ou je me trompe?memory_monitor()
s'exécute sur un thread distinct decount_prefixes()
, donc les seules manières dont l'une peut affecter l'autre sont le GIL et la file d'attente de messages vers laquelle je passememory_monitor()
. Je soupçonne que lors descount_prefixes()
appelssleep()
, cela encourage le contexte du thread à changer. Si celalong_running()
ne prend pas très longtemps, le contexte du thread peut ne pas basculer tant que vous n'avez passleep()
rappelé l' appelcount_prefixes()
. Si cela n'a pas de sens, postez une nouvelle question et liez-la à partir d'ici.Si vous voulez seulement regarder l'utilisation de la mémoire d'un objet, ( réponse à une autre question )
la source
asizeof
asizeof
peut contribuer au RSS, oui. Je ne sais pas trop ce que vous entendez par "lié à".tracemalloc
solution en dessous d'une amplitude plus rapideDivulgation:
Mais sympa à cause de sa simplicité:
Insérez simplement
using("Label")
où vous voulez voir ce qui se passe. Par exemplela source
usage[2]
vous regardezru_maxrss
, qui n'est que la partie du processus qui est résidente . Cela n'aidera pas beaucoup si le processus a été échangé sur le disque, même partiellement.resource
est un module spécifique à Unix qui ne fonctionne pas sous Windows.ru_maxrss
(c'est-à-direusage[2]
) sont ko, pas des pages, il n'est donc pas nécessaire de multiplier ce nombre parresource.getpagesize()
.Étant donné que la réponse acceptée et également la réponse la plus élevée suivante ont, à mon avis, quelques problèmes, je voudrais offrir une autre réponse qui est basée étroitement sur la réponse d'Ihor B. avec quelques petites mais importantes modifications.
Cette solution vous permet d'exécuter le profilage soit en encapsulant un appel de fonction avec la
profile
fonction et en l'appelant, soit en décorant votre fonction / méthode avec le@profile
décorateur.La première technique est utile lorsque vous souhaitez profiler du code tiers sans toucher à sa source, tandis que la deuxième technique est un peu plus «propre» et fonctionne mieux lorsque cela ne vous dérange pas de modifier la source de la fonction / méthode que vous voulez profiler.
J'ai également modifié la sortie, afin que vous obteniez RSS, VMS et mémoire partagée. Je ne me soucie pas beaucoup des valeurs "avant" et "après", mais seulement du delta, donc je les ai supprimées (si vous comparez à la réponse d'Ihor B.).
Code de profilage
Exemple d'utilisation, en supposant que le code ci-dessus est enregistré sous
profile.py
:Cela devrait entraîner une sortie similaire à celle ci-dessous:
Quelques notes finales importantes:
profile(my_function, arg)
à- dire pour profilermy_function(arg)
la source
Vous trouverez ci-dessous un simple décorateur de fonction qui permet de suivre la quantité de mémoire consommée par le processus avant l'appel de fonction, après l'appel de fonction et quelle est la différence:
Voici mon blog qui décrit tous les détails. ( lien archivé )
la source
process.memory_info().rss
pas être le casprocess.get_memory_info().rss
, du moins dans ubuntu et python 3.6. connexes stackoverflow.com/questions/41012058/psutil-error-on-macospeut-être que cela aide:
< voir plus >
la source
la source