Sometimes your program starts to eating a lot of memory, and you try to find out where is problem. There is variety of tools that can help you, and I wanted to tell about simple tool named asizeof of Pympler lib.

Pympler has 2 trackers to measure, monitor and analyze the memory behavior of Python objects. These trackers are muppy and Class Tracker. They also can help you investigate memory leaks.

There is a built-in sys.getsizeof() method, which returns the size of pure Python object only. Example:

>>> import sys
>>> sys.getsizeof(None)
16
>>> sys.getsizeof([])
64
>>> sys.getsizeof('a')
50
>>> sys.getsizeof(['a'])
72
>>> sys.getsizeof(['avadakedavra'])
72

In contrast, asizeof.asizeof() recursively searches for inner values, and counts whole size of object, including size of inner items:

>>> from pympler import asizeof
>>> asizeof.asizeof(None)
16
>>> asizeof.asizeof([])
64
>>> asizeof.asizeof('a')
56
>>> asizeof.asizeof(['a'])
128
>>> asizeof.asizeof(['avadakedavra'])
136

You can find a bottleneck in your script using asizeof by checking the size of values in your script. In complex and complicated scripts, probably we will need another more convenient tools, but in small scripts asizeof will be handy.

Asizeof can be used when you intuitively guess which variable can be problematic, and check its size, and to confirm the hunch. But if you totally do not know where the issue may be, and if your problematic code consist of dozens or hundreds of lines, then better to use memory profilers, because you cannot write print(asizeof()) on every variable.

Example:

from pympler import asizeof

class Empty(object):
    pass

class Dummy(object):
    def __init__(self):
        self.a = ['apple', 'banana', ['foo', 'bar', ['tiger', 'leo']]]
        self.b = {'key1': 'val1', 'key2': 'val2'}
        self.c = bytearray(1024*1024*4)
        self.d = self


def investigated_function():
    sometuple = (4, 10, -2,)
    for i in range(1000):
        empty = Empty()
        dummy = Dummy()
        # do_something_with(dummy)

If we run investigated_function(), it will consume our memory, and we want to investigate where is the problem. You just check values, e.g.:

print( asizeof.asizeof(sometuple) )
print( asizeof.asizeof(empty) )
print( asizeof.asizeof(dummy) )
168
152
4195944

and you can see that problem is in dummy instance, which is 4,195,944 bytes, which is around 4Mb. Also you can use asizeof.asizesof function (plural, "A Sizes Of"):

print( asizeof.asizesof(dummy.a, dummy.b, dummy.c, dummy.d) )
# returns sizes of individual values
(592, 512, 4194368, 472)

And from above command we can see, that dummy.c takes a lot of memory, which is an attribute of Dummy class:

self.c = bytearray(1024*1024*4)
Arthur Sultanbekov

Arthur Sultanbekov

Engineer

Joined January 2017. A geophysician in past, but decided that web is more interesting for him. Previous work was at small Russian telephony company. Learning python/Django and Javascript languages, web development and Linux administration.