2009-02-19 8 views
22

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:Comment puis-je vérifier l'utilisation de la mémoire des objets dans iPython?

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

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

double

Find out how much memory is being used by an object in Python

+0

en double : http://stackoverflow.com/questions/33978/find-out-how-much-memory-is-being-used-by-an-object-in-python, http://stackoverflow.com/questions/512893/memory-use-in-large-data-structures-manipulation-processing –

+0

Egalement en rapport: http://stackoverflow.com/questions/13566 4/comment-beaucoup-octets-par-élément-sont-là-dans-un-python-list-tuple/159844 – Constantin

+1

Désolé. Je veux juste demander s'il y a une implémentation de ces fonctionnalités dans ipython, ou un module pour cela en ajoutant la fonction "magic" dans ipython (puisque je l'utilise pour tester beaucoup.) – Ross

Répondre

32

Malheureusement, ce n'est pas possible, mais il y a plusieurs façons de rapprocher la réponse:

  1. pour des objets très simples (par exemple, ints, chaînes, flottants, 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 John Mulder's solution.

  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 dictionnaire contient des chaînes de caractères et d'autres objets en tant que valeurs. Ces autres objets peuvent être partagés. Puisque pickle essaie toujours de faire une sérialisation complète de l'objet, il surestimera toujours la quantité de mémoire nécessaire pour stocker un objet.

+1

Mais si vous choisissez une liste contenant tous les objets racine qui vous intéressent, il n'y aura pas de surestimation. – Constantin

+0

Merci beaucoup. Mais je me demande si le cornichon fera de la compression ou non. – Ross

+0

Non, le cornichon ne se comprime pas. Cela élimine simplement la redondance. –

13

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

Voici une thread aborder une question similaire

La solution proposée est d'écrire votre propre ... en utilisant des estimations de la taille connue des primitives, les frais généraux d'objets de python, et les tailles de construction dans les types de conteneurs.

Étant donné que le code n'est pas si longtemps, 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 
+0

vous avez oublié le flotteur .. – drevicko

+1

C'est une solution assez durement codée. Cela ne fonctionnerait pas si nous avons une liste de grands dictionnaires ou toute autre structure de données! – user2685079

16

Si vous utilisez un numpy array, 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 
+3

Ceci est également montré par la magie IPython '% whos'. – gerrit

2

pour la taille totale de la population locale (en Mo):

from sys import getsizeof 
sum([getsizeof(k) for k in locals().keys()])/10**6 
+2

cela obtient la taille de la clé, pas la valeur. aussi, pas besoin d'utiliser une liste de compréhension quand un générateur fera l'affaire – Kapocsi