Глубокая версия sys.getsizeof

Я хочу вычислить память, используемую объектом. sys.getsizeof отлично, но неглубоко (например, вызывается в списке, он не будет включать память, занятую элементами списка).

Я хотел бы написать общую "глубокую" версию sys.getsizeof. Я понимаю, что есть некоторая двусмысленность в определении "глубокий"; я совершенно доволен определение, за которым следует copy.deepcopy.

вот моя первая попытка:

def get_deep_sizeof(x, level=0, processed=None):
    if processed is None:
        # we're here only if this function is called by client code, not recursively
        processed = set()
    processed.add(id(x))
    mem = sys.getsizeof(x)
    if isinstance(x, collections.Iterable) and not isinstance(x, str):
        for xx in x:
            if id(xx) in processed:
                continue
            mem += get_deep_sizeof(xx, level+1, processed)
            if isinstance(x, dict):
                mem += get_deep_sizeof(x[xx], level+1, processed)
    return mem

он страдает от двух известные проблемы, и неизвестное количество неизвестных проблем:

  • я не знаю, как пройти общий контейнер таким образом, чтобы захватить все связанные объекты. Поэтому я повторил использование in, и жестко закодированный случай словаря (для включения значений, а не только ключей). Очевидно, что это не будет работать для других классов, таких как dictionary.
  • я жесткий код исключения str (который является итерируемым, и еще нет ссылки на любой другой объекты.) Опять же, это сломается, если будет больше таких объектов.

Я подозреваю, что с помощью in - это не очень хорошая идея, но я не уверен, что еще делать.

1 ответов


думаю, что Pympler уже опередил вас на удар по этому.

из их документации:

>>> from pympler.asizeof import asizeof
>>> obj = [1, 2, (3, 4), 'text']
>>> asizeof(obj)
176

Если вы хотите конкретный пример, вы можете найти источник asizeof здесь.