python - 在 python 中导致 outOfMemoryExeption 有多容易?

标签 python memory out-of-memory

我在 python 中使用 pygame 编写了一个拼字蜜蜂程序,它工作正常,但我一直在用 7 个单词测试它,而不是更多。
我担心,如果与 300 个单词一起使用,它可能会导致内存被填满。 请记住有 2 个数组:一个保存默认单词列表,另一个保存随机单词。

最佳答案

您真的不必担心。 Python 并不是内存消耗大到仅仅 600 个单词就会引起问题。

稍加小心,您可以直接测量内存需求。 sys.getsizeof() function让您测量给定 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 uses references for everything ,包括列表内容。考虑到这一点。

所以让我们加载 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 字节。这甚至不到 20KB。

但是,您说,您有 2 个列表。但是第二个列表不会包含您的单词的副本,它只是对现有单词的更多引用,因此只需要另外 2464 字节,即 2KB。

对于 300 个随机英语单词,在两个列表中,您的总内存要求约为 20KB 内存

在 8GB 的​​机器上,你不会有任何问题。请注意,我一次性将整个 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

这大约需要 15MB 的内存,用于将近 23.6 万个单词。

如果您担心包含更多对象的大型程序,您也可以使用 tracemalloc library获取有关内存使用的统计信息:

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() 测量结果。

关于python - 在 python 中导致 outOfMemoryExeption 有多容易?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53460568/

相关文章:

Python列表实现和pympler测量

c# - WPF 中的 OpenGL 控件因 OOM 异常而崩溃

android - 在Android中上传大文件而不会出现内存不足错误

python - 排序 XML 文件

python - OOP Python 向基类添加一些属性?

python - 在 python 中执行时 autossh 不工作

java - Ubuntu 内核杀死 java 进程,即使它没有内存不足

python - 如果我有 Intel Core i7 和 64 位 Windows 7,要安装哪个 python?

c - 在C中释放结构内部的结构数组

memory - 如何知道地址是否是 64 位对齐的?