web-dev-qa-db-fra.com

Comment puis-je vérifier l'utilisation de la mémoire des objets dans iPython?

J'utilise iPython pour exécuter mon code. Je me demande s'il existe un module ou une commande qui me permettrait de vérifier l'utilisation de la mémoire d'un objet. Par exemple:

In [1]: a = range(10000)
In [2]: %memusage a
Out[2]: 1MB

Quelque chose comme %memusage <object> et retourne la mémoire utilisée par l'objet.

Dupliquer

Découvrez la quantité de mémoire utilisée par un objet en Python

36
Ross

Malheureusement, ce n'est pas possible, mais il existe un certain nombre de façons d'approximer la réponse:

  1. pour les objets très simples (par exemple les entiers, les chaînes, les flottants, les doubles) qui sont représentés plus ou moins comme de simples types de langage C, vous pouvez simplement calculer le nombre d'octets comme avec solution de John Mulder .

  2. Pour les objets plus complexes, une bonne approximation consiste à sérialiser l'objet en une chaîne à l'aide de cPickle.dumps. La longueur de la chaîne est une bonne approximation de la quantité de mémoire requise pour stocker un objet.

Il existe un gros problème avec la solution 2, à savoir que les objets contiennent généralement des références à d'autres objets. Par exemple, un dict contient des clés de chaîne et d'autres objets comme valeurs. Ces autres objets peuvent être partagés. Étant donné que pickle essaie toujours de faire une sérialisation complète de l'objet, il surestimera toujours la quantité de mémoire requise pour stocker un objet.

54
Salim Fadhley

Si vous utilisez un tableau numpy , vous pouvez utiliser l'attribut ndarray.nbytes pour évaluer sa taille en mémoire:

from pylab import *   
d = array([2,3,4,5])   
d.nbytes
#Output: 32
20
HoWil

MISE À JOUR: Voici n autre , recette peut-être plus approfondie pour estimer la taille d'un objet python.

Voici un thread répondant à une question similaire

La solution proposée est d'écrire la vôtre ... en utilisant quelques estimations de la taille connue des primitives, de la surcharge des objets de python et des tailles des types de conteneurs intégrés.

Étant donné que le code n'est pas si long, voici une copie directe de celui-ci:

def sizeof(obj):
    """APPROXIMATE memory taken by some Python objects in 
    the current 32-bit CPython implementation.

    Excludes the space used by items in containers; does not
    take into account overhead of memory allocation from the
    operating system, or over-allocation by lists and dicts.
    """
    T = type(obj)
    if T is int:
        kind = "fixed"
        container = False
        size = 4
    Elif T is list or T is Tuple:
        kind = "variable"
        container = True
        size = 4*len(obj)
    Elif T is dict:
        kind = "variable"
        container = True
        size = 144
        if len(obj) > 8:
            size += 12*(len(obj)-8)
    Elif T is str:
        kind = "variable"
        container = False
        size = len(obj) + 1
    else:
        raise TypeError("don't know about this kind of object")
    if kind == "fixed":
        overhead = 8
    else: # "variable"
        overhead = 12
    if container:
        garbage_collector = 8
    else:
        garbage_collector = 0
    malloc = 8 # in most cases
    size = size + overhead + garbage_collector + malloc
    # Round to nearest multiple of 8 bytes
    x = size % 8
    if x != 0:
        size += 8-x
        size = (size + 8)
    return size
14
John Mulder

J'essayais de comprendre comment faire exactement cela pour moi. J'ai essayé plusieurs solutions sur cette page et d'autres pages. J'ai ensuite fait quelques recherches et suis tombé sur https://ipython-books.github.io/44-profiling-the-memory-usage-of-your-code-with-memory_profiler/ qui semble donner une solution alternative. L'essentiel de la solution: utilisez %mprun Dans ipython.

  1. Tout d'abord, installez memory_profiler: pip install memory_profiler
  2. Démarrez ipython et chargez memory_profiler:% load_ext memory_profiler
  3. Créez une fonction dans un fichier physique, disons, myfunc.py (Important: % mprun ne peut être utilisé que sur des fonctions définies dans des fichiers physiques ) . Créez l'objet en question dans une fonction, par exemple:
# myfunc.py
def myfunc():
    # create the object, e.g.
    a = [*range(10000)]
  1. Courir
from myfunc import myfunc
%mprun -T mprof -f myfunc myfunc()

qui génère le fichier mprof. Le contenu est également affiché:

Line #    Mem usage    Increment   Line Contents
================================================
     1     49.1 MiB     49.1 MiB   def myfunc():
     2                                 # create the object, e.g.
     3     49.4 MiB      0.3 MiB       a = [*range(10000)]

D'après l'inrement de la ligne 3, nous savons que la mémoire utilisée par a est de 0,3 MiB.

Essayons a = [*range(100000)]:

# myfunc1.py
def myfunc1():
    # create the object, e.g.
    a = [*range(100000)]

Courir

from myfunc1 import myfunc1
%mprun -T mprof1 -f myfunc1 myfunc1()

Line #    Mem usage    Increment   Line Contents
================================================
     1     49.2 MiB     49.2 MiB   def myfunc1():
     2                                 # create the object, e.g.
     3     52.3 MiB      3.0 MiB       a = [*range(100000)]

semble être conforme à nos attentes.

1
mikey