Глубокая версия 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
не очень хорошая идея, но я не уверен, что еще можно сделать.