Source code for fdi.utils.totalsize

""" https://code.activestate.com/recipes/577504/ """
from __future__ import print_function
from collections import Set, Mapping, deque
from numbers import Number
from gc import get_referents
from types import ModuleType, FunctionType
import sys
from sys import getsizeof, stderr
from itertools import chain
from collections import deque
try:
    from reprlib import repr
except ImportError:
    pass


[docs]def total_size(o, handlers={}, verbose=False): """ Returns the approximate memory footprint an object and all of its contents. Automatically finds the contents of the following builtin containers and their subclasses: tuple, list, deque, dict, set and frozenset. To search other containers, add handlers to iterate over their contents: handlers = {SomeContainerClass: iter, OtherContainerClass: OtherContainerClass.get_elements} """ def dict_handler(d): return chain.from_iterable(d.items()) all_handlers = {tuple: iter, list: iter, deque: iter, dict: dict_handler, set: iter, frozenset: iter, } all_handlers.update(handlers) # user handlers take precedence seen = set() # track which object id's have already been seen # estimate sizeof object without __sizeof__ default_size = getsizeof(0) def sizeof(o): if id(o) in seen: # do not double count the same object return 0 seen.add(id(o)) s = getsizeof(o, default_size) if verbose: print(s, type(o), repr(o), file=stderr) for typ, handler in all_handlers.items(): if isinstance(o, typ): s += sum(map(sizeof, handler(o))) break return s return sizeof(o)
##### Example call ##### if __name__ == '__main__': d = dict(a=1, b=2, c=3, d=[4, 5, 6, 7], e='a string of chars') print(total_size(d, verbose=True)) """ https://stackoverflow.com/a/30316760/13472124 Aaron Hall""" # Custom objects know their class. # Function objects seem to know way too much, including modules. # Exclude modules as well. BLACKLIST = type, ModuleType, FunctionType
[docs]def getsize_gc(obj): """sum size of object & members.""" if isinstance(obj, BLACKLIST): raise TypeError( 'getsize() does not take argument of type: ' + str(type(obj))) seen_ids = set() size = 0 objects = [obj] while objects: need_referents = [] for obj in objects: if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids: seen_ids.add(id(obj)) size += sys.getsizeof(obj) need_referents.append(obj) objects = get_referents(*need_referents) return size
try: # Python 2 zero_depth_bases = (basestring, Number, xrange, bytearray) iteritems = 'iteritems' except NameError: # Python 3 zero_depth_bases = (str, bytes, Number, range, bytearray) iteritems = 'items'
[docs]def getsize_rec(obj_0): """Recursively iterate to sum size of object & members.""" _seen_ids = set() def inner(obj): obj_id = id(obj) if obj_id in _seen_ids: return 0 _seen_ids.add(obj_id) size = sys.getsizeof(obj) if isinstance(obj, zero_depth_bases): pass # bypass remaining control flow and return elif isinstance(obj, (tuple, list, Set, deque)): size += sum(inner(i) for i in obj) elif isinstance(obj, Mapping) or hasattr(obj, iteritems): size += sum(inner(k) + inner(v) for k, v in getattr(obj, iteritems)()) # Check for custom object instances - may subclass above too if hasattr(obj, '__dict__'): size += inner(vars(obj)) if hasattr(obj, '__slots__'): # can have __slots__ with __dict__ size += sum(inner(getattr(obj, s)) for s in obj.__slots__ if hasattr(obj, s)) return size return inner(obj_0)