293 votes

Comment puis-je profiler l'utilisation de la mémoire en Python ?

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 suis déjà familiarisé avec le module Python standard pour le profilage du temps d'exécution (pour la plupart des choses, j'ai trouvé la fonction magique timeit dans IPython suffisante), mais je suis également intéressé par l'utilisation de la mémoire afin de pouvoir 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 au recalcul de ces valeurs en cas de besoin). Existe-t-il un module capable d'établir le profil de l'utilisation de la mémoire d'une fonction donnée ?

1 votes

Duplicata de Quel profileur de mémoire Python est recommandé ? . A mon avis, la meilleure réponse en 2019 est profileur de mémoire

13voto

Ihor B. Points 311

Voici un décorateur de fonction simple qui permet de suivre la quantité de mémoire consommée par le processus avant l'appel de la fonction, après l'appel de la fonction, et quelle est la différence :

import time
import os
import psutil

def elapsed_since(start):
    return time.strftime("%H:%M:%S", time.gmtime(time.time() - start))

def get_process_memory():
    process = psutil.Process(os.getpid())
    mem_info = process.memory_info()
    return mem_info.rss

def profile(func):
    def wrapper(*args, **kwargs):
        mem_before = get_process_memory()
        start = time.time()
        result = func(*args, **kwargs)
        elapsed_time = elapsed_since(start)
        mem_after = get_process_memory()
        print("{}: memory before: {:,}, after: {:,}, consumed: {:,}; exec time: {}".format(
            func.__name__,
            mem_before, mem_after, mem_after - mem_before,
            elapsed_time))
        return result
    return wrapper

Voici mon blog qui décrit tous les détails. ( lien archivé )

4voto

madjardi Points 475

Ça peut aider :
< voir le complément >

pip install gprof2dot
sudo apt-get install graphviz

gprof2dot -f pstats profile_for_func1_001 | dot -Tpng -o profile.png

def profileit(name):
    """
    @profileit("profile_for_func1_001")
    """
    def inner(func):
        def wrapper(*args, **kwargs):
            prof = cProfile.Profile()
            retval = prof.runcall(func, *args, **kwargs)
            # Note use of name from outer scope
            prof.dump_stats(name)
            return retval
        return wrapper
    return inner

@profileit("profile_for_func1_001")
def func1(...)

3voto

nremenyi Points 21

Un exemple simple pour calculer l'utilisation de la mémoire d'un bloc de codes / fonction en utilisant memory_profile, tout en retournant le résultat de la fonction :

import memory_profiler as mp

def fun(n):
    tmp = []
    for i in range(n):
        tmp.extend(list(range(i*i)))
    return "XXXXX"

calculer l'utilisation de la mémoire avant d'exécuter le code puis calculer l'utilisation maximale pendant le code :

start_mem = mp.memory_usage(max_usage=True)
res = mp.memory_usage(proc=(fun, [100]), max_usage=True, retval=True) 
print('start mem', start_mem)
print('max mem', res[0][0])
print('used mem', res[0][0]-start_mem)
print('fun output', res[1])

calculer l'utilisation en points d'échantillonnage pendant l'exécution de la fonction :

res = mp.memory_usage((fun, [100]), interval=.001, retval=True)
print('min mem', min(res[0]))
print('max mem', max(res[0]))
print('used mem', max(res[0])-min(res[0]))
print('fun output', res[1])

Crédits : @skeept

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X