Чтение вывода Pythons memory_profiler - PullRequest
0 голосов
/ 30 августа 2018

У меня проблема с пониманием вывода memory_profiler s. В основном это выглядит так:

Filename: tspviz.py

Line #    Mem usage    Increment   Line Contents
================================================
     7  34.589844 MiB  34.589844 MiB   @profile(precision=6)
     8                             def parse_arguments():
     9  34.917969 MiB   0.328125 MiB       a = [x**2 for x in range(10000)]

В 9-й строке мы ясно видим, что мы используем некоторую память. Теперь я измерил размер этого списка с sys.getsizeof(). И я дважды проверил, действительно ли это список целых:

print(sys.getsizeof(a))
print(type(a[0]))

И вот что я получил:

87624
<class 'int'>

Ну, теперь есть проблема. Как я проверял, например, int в Python имеет размер 28 на моей 64-битной Windows-машине. Я не знаю, правильно ли это. Но даже так. 10000 * 28 = 0,28 МБ. И 0.28 MB = 0.267028809 MiB (на выходе memory_profiler отображается MiB). Теперь проблема в том, что в таблице есть 0.328125 MiB, поэтому разница составляет 0.061096191 МБ.

Мое беспокойство здесь заключается в том, действительно ли для построения списка в Python требуется большой объем памяти, или я что-то неправильно интерпретирую?

И П.С .: Почему, когда этот список a имел длину 1000000, число в столбце Increment для этой строки, когда я его создавал, было равно -9xxx MiB? Я имею в виду, почему отрицательное число?

1 Ответ

0 голосов
/ 01 сентября 2018

Списки Python хранят не сами объекты, а ссылки на них. 64-битная версия Python использует 8 байтов на ссылку, поэтому 10000 ints требует 80000 байтов. Из вашего примера sys.getsizeof(a) вернул 87624, поскольку для эффективности списки выделяют дополнительное пространство, пропорциональное их размеру. Смотрите этот пост больше .

Пространство, занятое int, варьируется в зависимости от его размера, но от int s до 2^30-1 кажется, что на 64-битном Python требуется 28 байт (кроме 0, который занимает всего 24 байт). Таким образом, в итоге размер, взятый списком, составляет 87624 + 279996 = 367620 байтов, что составляет около 0.35 MiB.

Расхождение между этим и выводом memory_profiler, вероятно, связано с this :

Этот модуль получает потребление памяти, запрашивая операционную ядро системы о количестве памяти текущего процесса выделено, что может немного отличаться от объема памяти это на самом деле используется интерпретатором Python. Кроме того, из-за того, как сборщик мусора работает в Python, результат может быть другим между платформами и даже между трассами.

...