Подтвердить что ты не робот

Python глубоко получает список с содержимым?

Я был удивлен, что sys.getsizeof( 10000*[x] ) составляет 40036 независимо от x: 0, "a", 1000 * "a", {}.
Существует ли deep_getsizeof который правильно рассматривает элементы, которые разделяют память?
(Вопрос пришел к рассмотрению таблиц базы данных в памяти, таких как диапазон (1000000) → названия провинций: список или диктофон?)
(Python 2.6.4 на mac ppc.)

Добавлено: 10000 * [ "Миссисипи" ] - 10000 указателей на один "Миссисипи", как отметили несколько человек. Попробуйте следующее:

nstates = [AlabamatoWyoming() for j in xrange(N)]

где AlabamatoWyoming() → строка "Алабама".. "Вайоминг". Что такое deep_getsizeof (nstates)?
(Как мы можем сказать?

  • правильный deep_getsizeof: трудный, ~ gc tracer
  • оценка из общего числа vm
  • внутреннее знание реализации python
  • догадка.

Добавлено 25jan: см. также when-does-python-allocate-new-memory-for-identical-strings

4b9b3361

Ответ 1

Посмотрите guppy/heapy; Я не слишком много играл с ним, но некоторые из моих сотрудников использовали его для профилирования памяти с хорошими результатами.

Документация может быть лучше, но this howto делает достойную работу по объяснению основных понятий.

Ответ 2

10000 * [x] создаст список из 10000 раз одного и того же объекта, поэтому sizeof на самом деле ближе к правилу, чем вы думаете. Тем не менее, глубокий sizeof очень проблематичен, потому что невозможно сказать Python, когда вы хотите остановить измерение. Каждый объект ссылается на объект типа. Следует ли подсчитать тип объекта? Что делать, если ссылка на объект типа является последней, поэтому, если вы удалили объект, объект типа тоже исчезнет? А если у вас несколько (разных) объектов в списке относятся к одному и тому же объекту строки? Должен ли он подсчитываться один раз или несколько раз?

Короче говоря, получение размера структуры данных очень сложно, и sys.getsizeof() никогда не добавлялось: S

Ответ 3

Если вы указываете только объекты с одинаковой длиной, вы можете получить более точный оценочный номер, выполнив это

def getSize(array):
    return sys.getsizeof(array) + len(array) * sys.getsizeof(array[0])

Очевидно, что это не подходит для строк с переменной длиной.

Если вы хотите только рассчитать размер для отладки или во время разработки, и вам не нужна производительность, вы можете рекурсивно перебирать все элементы и вычислять общий размер. Обратите внимание, что это решение не будет обрабатывать несколько ссылок на один и тот же объект.

Ответ 4

mylist = 10000 * [x] означает создание списка размером 10000 с 10000 ссылками на объект x.

Объект x не скопирован - в памяти существует только один.

Итак, чтобы использовать getizeof, это будет: sys.getsizeof(mylist) + sys.getsizeof(x)