Насколько легко вызвать outOfMemoryExeption в Python? - PullRequest
0 голосов
/ 24 ноября 2018

Я использую программу правописания на python, используя pygame, и она работает нормально, но я тестировал ее с 7 словами, не более.
Я беспокоюсь, что, если использовать с 300 словами, это может привести к тому, что памятьзаполнить.помните, что есть 2 массива: один содержит список слов по умолчанию, а другой содержит рандомизированные слова.

Ответы [ 2 ]

0 голосов
/ 24 ноября 2018

Вам действительно не нужно беспокоиться.Python - это не такая проблема с памятью, чтобы вызывать проблемы только с 600 словами.

С некоторой осторожностью вы можете измерить требования к памяти напрямую.Функция sys.getsizeof() позволяет вам измерить прямые требования к памяти для данного объекта Python (только прямая память, а не все, на что он ссылается!).Вы можете использовать это для измерения отдельных строк:

>>> import sys
>>> sys.getsizeof("Hello!")
55
>>> sys.getsizeof("memoryfootprint")
64

Точные размеры зависят от версии Python и вашей ОС.Строковому объекту Python требуется базовый объем памяти для большого количества информации бухгалтерского учета, а затем 1, 2 или 4 байта на символ, в зависимости от самой высокой кодовой точки Unicode.Для ASCII это всего один байт на букву.Python 3.7 в моей системе Mac OS X использует 49 байт для части учета.

Получение размера объекта Python list означает, что вы получаете только требования к памяти для списка объектов , а невсе, что хранится «в» списке.Вы можете многократно добавлять один и тот же объект в список, и вы не получите копии, потому что Python использует ссылки для всего , включая содержимое списка.Примите это во внимание.

Итак, давайте загрузим 300 случайных слов и создадим два списка, чтобы увидеть, что потребуется для памяти:

>>> import random
>>> words = list(map(str.strip, open('/usr/share/dict/words')))  # big file of words, present on many computers
>>> words = random.sample(words, 300)  # just use 300
>>> words[:10]
['fourer', 'tampon', 'Minyadidae', 'digallic', 'euploid', 'Mograbi', 'sketchbook', 'annul', 'ambilogy', 'outtalent']
>>> import statistics
>>> statistics.mean(map(len, words))
9.346666666666666
>>> statistics.median(map(len, words))
9.0
>>> statistics.mode(map(len, words))
10
>>> sys.getsizeof(words)
2464
>>> sum(sys.getsizeof(word) for word in words)
17504

Это один список с 300 уникальными словами ссредняя длина чуть более 9 символов, для этого требуется 2464 байта для списка и 17504 байта для самих слов.Это меньше, чем даже 20 КБ.

Но, вы говорите, у вас есть 2 списка.Но во втором списке не будет копий ваших слов, это просто больше ссылок на существующие слова, поэтому потребуется всего 2464 байта, поэтому 2 КБ.

Для 300 случайных английских слов, вдва списка, ваши общие требования к памяти составляют около 20 КБ памяти .

На машине 8 ГБ у вас не будет никаких проблем.Обратите внимание, что я загрузил файл целом words за один раз в свой компьютер, а затем сократил его до 300 случайных слов.Вот сколько памяти требуется для всего начального списка:

>>> words = list(map(str.strip, open('/usr/share/dict/words')))
>>> len(words)
235886
>>> sum(sys.getsizeof(word) for word in words)
13815637
>>> sys.getsizeof(words)
2007112

Это примерно 15 МБ памяти для почти 236 тысяч слов.

Если вы беспокоитесь о больших программах с большим количеством объектов,что вы также можете использовать библиотеку tracemalloc для получения статистики об использовании памяти:

last = None
def display_memory_change(msg):
    global last
    snap = tracemalloc.take_snapshot()
    statdiff, last = snap.compare_to(last, 'filename', True), snap
    tot = sum(s.size for s in statdiff)
    change = sum(s.size_diff for s in statdiff)
    print('{:>20} (Tot: {:6.1f} MiB, Inc: {:6.1f} MiB)'.format(
        msg, tot / 2 ** 20, change / 2 ** 20))


# at the start, get a baseline
tracemalloc.start()
last = tracemalloc.take_snapshot()

# create objects, run more code, etc.

display_memory_change("Some message as to what has been done")

# run some more code.

display_memory_change("Show some more statistics")

Использование приведенного выше кода для измерения чтения всех этих слов:

tracemalloc.start()
last = tracemalloc.take_snapshot()
display_memory_change("Baseline")

words = list(map(str.strip, open('/usr/share/dict/words')))

display_memory_change("Loaded words list")

дает вывод

            Baseline (Tot:    0.0 MiB, Inc:    0.0 MiB)
   Loaded words list (Tot:   15.1 MiB, Inc:   15.1 MiB)

, подтверждающий мои sys.getsizeof() измерения.

0 голосов
/ 24 ноября 2018

Один хороший способ выяснить это - попробовать.

Вы можете поставить линию в середине вашей программы, чтобы распечатать, сколько памяти она использует :

import os
import psutil
process = psutil.Process(os.getpid())
print(process.memory_info().rss)

Попробуйте запустить вашу программу с различным количеством слов и отобразить результаты:

graph plotting total memory vs. number of words

Затем вы можете предсказать, сколько слов потребуется, чтобыизрасходуйте всю свою память.

Следует учесть еще несколько моментов:

  • Если вы используете 32-битный Python, ваша общая память будет ограничена 32-битным адресным пространствомпримерно до 4 ГБ.
  • Вероятно, ваш компьютер использует диск для увеличения виртуальной памяти сверх объема оперативной памяти.Таким образом, даже если у вас есть только 1 ГБ ОЗУ, вы можете обнаружить, что можете использовать 3 ГБ памяти в вашей программе.
  • Для небольших списков слов, которые вы используете, вы почти никогда не хватает памяти, если в вашей программе нет ошибки.По моему опыту, OutOfMemory почти всегда, потому что я допустил ошибку.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...