gpt4 book ai didi

内存优化的 Python 技巧

转载 作者:太空狗 更新时间:2023-10-29 18:19:42 27 4
gpt4 key购买 nike

我需要优化我的应用程序的 RAM 使用率。
请省去那些告诉我在编写 Python 代码时不应该关心内存的讲座。我有内存问题,因为我使用非常大的默认字典(是的,我也想快点)。我目前的内存消耗是 350MB 并且还在增长。我已经无法使用共享主机,如果我的 Apache 打开更多进程,内存就会翻倍和三倍……而且很昂贵。
我已经完成了广泛的分析并且我确切地知道我的问题出在哪里。
我有几个带有 Unicode 键的大型(> 100K 个条目)词典。字典从 140 字节开始并且增长很快,但更大的问题是键。 Python 优化内存中的字符串(或者我读过的),以便查找可以是 ID 比较(“实习”它们)。不确定 unicode 字符串也是如此(我无法“实习”它们)。
字典中存储的对象是元组列表(an_object, an int, an int)。

my_big_dict[some_unicode_string].append((my_object, an_int, another_int))

我已经发现拆分成多个字典是值得的,因为元组占用大量空间...
我发现我可以通过在将字符串用作键之前对字符串进行哈希处理来节省 RAM!但遗憾的是,我在 32 位系统上遇到了生日冲突。 (附带问题:是否有可以在 32 位系统上使用的 64 位 key 字典?)

Linux(生产)和 Windows 上的 Python 2.6.5。关于优化字典/列表/元组的内存使用的任何提示?我什至想到了使用 C——我不在乎这一小段代码是否丑陋。它只是一个单一的位置。

提前致谢!

最佳答案

我建议如下:将所有值存储在数据库中,并在内存中保留一个字典,其中字符串哈希作为键。如果发生冲突,则从数据库中获取值,否则(绝大多数情况)使用字典。实际上,它将是一个巨大的缓存。

Python 中字典的一个问题是它们占用大量空间:即使是 int-int 字典在 32 位系统上每个键值对也使用 45-80 字节。同时,array.array('i') 每一对整数仅使用 8 个字节,通过一些簿记,可以合理地实现基于数组的快速 int → int 字典。

一旦你有一个内存高效的 int-int 字典实现,将你的 string → (object, int, int) 字典分成三个字典并使用散列而不是完整的字符串。你会得到一个 int → object 和两个 int → int 字典。如下模拟 int → object 字典:保留对象列表并将对象的索引存储为 int → int 字典的值。

我确实意识到获取基于数组的字典涉及大量编码。我遇到了与您类似的问题,并且我已经实现了一个相当快、非常节省内存的通用散列整数字典。 Here's my code (BSD 许可证)。它是基于数组的(每对 8 个字节),它负责 key 散列和冲突检查,它在写入期间保持数组(实际上是几个较小的数组)的顺序,并在读取时进行二进制搜索。您的代码被简化为:

dictionary = HashIntDict(checking = HashIntDict.CHK_SHOUTING)
# ...
database.store(k, v)
try:
dictionary[k] = v
except CollisionError:
pass
# ...
try:
v = dictionary[k]
except CollisionError:
v = database.fetch(k)

checking 参数指定发生冲突时发生的情况:CHK_SHOUTING 在读取和写入时引发 CollisionErrorCHK_DELETING 在读取时返回 None,在写入时保持沉默,CHK_IGNORING 不进行碰撞检查。

下面简单介绍一下我的实现,欢迎指点优化!顶级数据结构是数组的常规字典。每个数组最多包含 2^16 = 65536 个整数对(2^32 的平方根)。键 k 和相应的值 v 都存储在第 k/65536 数组中。数组按需初始化并按键保持排序。二进制搜索在每次读取和写入时执行。碰撞检查是一个选项。如果启用,覆盖现有键的尝试将从字典中删除键和关联值,将键添加到一组冲突键中,并(再次,可选)引发异常。

关于内存优化的 Python 技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3021264/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com