Глубокая версия 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 и жестко закодировал случай словаря (чтобы включить значения, а не только ключи). Очевидно, что это не будет работать для других классов, таких как словарь.
  • Мне пришлось жестко закодировать исключение str (которое является итерационным и все же не имеет ссылок на какие-либо другие объекты). Опять же, это сломается, если есть больше объектов как это.
Я подозреваю, что использовать in не очень хорошая идея, но я не уверен, что еще можно сделать.
1 7

1 ответ:

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

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

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

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