Tushar Jajodia
Tushar Jajodia

Reputation: 451

Why does sys.getsizeof() report the same size for two instances even though one has an extra attribute?

import sys

class MyObject:
    def __init__(self,name,salary):
        self.name = name
        self.salary = salary

obj1 = MyObject("Tushar", 50)
obj2 = MyObject("Tushar", 50)
obj2.age = 20

print(sys.getsizeof(obj1))  # 56
print(sys.getsizeof(obj2))  # 56

Why is obj2 only 56 bytes when it has an extra age attribute?

Upvotes: 0

Views: 548

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121654

sys.getsizeof() only gives you the system memory use for the direct reference. Instance objects don't store attributes directly, by default those are stored in a dictionary object referenced by the __dict__ name. And dictionaries store keys and values as references too, sys.getsizeof() would only give you the memory size of the dictionary internal C arrays and other internal bookkeeping attributes, not the keys or values themselves.

From the sys.getsizeof() documentation:

Only the memory consumption directly attributed to the object is accounted for, not the memory consumption of objects it refers to.

You'd have to recursively collect object sizes until you run out of attributes or key-value pairs, etc. The documentation links to this example code to show you how to do this.

That specific recipe has no support for instances but here passing in the __dict__ attribute of your objects should suffice:

>>> total_size(obj1.__dict__)
303
>>> total_size(obj2.__dict__)
383

so the two objects have different total size attribute dictionaries.

Note that there are many places where Python caches or interns objects, so don't take these memory sizes as absolutes. For example, small integers are interned, so there is only ever a single 50 integer object in CPython memory, but it was counted separately in the above total_size() output.

And modern CPython versions can also save memory by having the __dict__ dictionary objects of those two instances share data on the keys, in the assumption that the vast majority of instances of a given class will have the same attributes.

Take this into account when analysing sys.getsizeof() data. If you wanted to profile Python memory use, you'd be much better of learning how to use the tracemalloc tool first.

Upvotes: 3

Related Questions