Python глубоко получает список с содержимым? - PullRequest
19 голосов
/ 22 января 2010

Я был удивлен, что sys.getsizeof( 10000*[x] ) равно 40036 независимо от x: 0, «a», 1000 * «a», {}.
Есть ли deep_getsizeof который правильно считает элементы, которые разделяют память?
(Вопрос возник из просмотра таблиц базы данных в памяти, таких как диапазон (1000000) -> названия провинций: список или дикт??
(Python - 2.6.4 на компьютере Mac.)

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

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

где AlabamatoWyoming () -> строка "Alabama" .. "Wyoming". Что такое deep_getsizeof (nstates)?
(Как мы можем сказать?

  • правильный deep_getsizeof: трудный, ~ gc tracer
  • оценка от общего объема
  • внутреннее знание реализации Python
  • думаю.

Добавлено 25ян: см. также когда-делает-Python-выделить-новую-память-для-идентичных строк

Ответы [ 5 ]

15 голосов
/ 22 января 2010

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

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

5 голосов
/ 22 января 2010

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

Документация могла бы быть лучше, но это руководство хорошо объясняет основные понятия.

5 голосов
/ 22 января 2010

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

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

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

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

1 голос
/ 06 марта 2019

Я написал инструмент под названием RememberMe именно для этого. Основное использование:

from rememberme import memory
a = [1, 2, 3]
b = [a, a, a]
print(memory(a))  # 172 bytes
print(memory(b))  # 260 bytes. Duplication counted only once.

Надеюсь, это поможет.

0 голосов
/ 22 января 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...