Tal*_*iss 10 python optimization memory-management
我需要优化应用程序的RAM使用率.
请不要在讲课时告诉我在编写Python时我不应该关心内存.我有一个内存问题,因为我使用非常大的默认字典(是的,我也想要快速).我目前的内存消耗是350MB并且还在增长.我已经不能使用共享主机了,如果我的Apache打开更多进程,内存会翻倍并增加三倍......而且价格昂贵.
我做了大量的分析,我确切地知道我的问题在哪里.
我有几个带有Unicode密钥的大型(> 100K条目)词典.字典从140字节开始并且增长很快,但更大的问题是密钥.Python优化了内存中的字符串(或者我已经读过),因此查找可以进行ID比较('实际').不确定这对于unicode字符串也是如此(我无法'实习'它们).
存储在字典中的对象是元组列表(an_object,int,int).
my_big_dict [some_unicode_string] .append((my_object,an_int,another_int))
我已经发现拆分到几个字典是值得的,因为元组占用了大量的空间......
我发现在使用它们作为键之前我可以通过散列字符串来节省RAM!但是,遗憾的是,我遇到了32位系统的生日碰撞.(附带问题:我可以在32位系统上使用64位密钥字典吗?)
Linux(生产)和Windows上的Python 2.6.5.有关优化字典/列表/元组的内存使用的任何提示?我甚至想过使用C - 我不在乎这段很小的代码是否丑陋.这只是一个独特的位置.
提前致谢!
Bol*_*olo 11
我建议如下:将所有值存储在DB中,并使用字符串哈希作为键保留内存中的字典.如果发生冲突,则从DB获取值,否则(绝大多数情况下)使用字典.实际上,它将是一个巨大的缓存.
Python中字典的一个问题是它们占用了大量空间:即使是int-int字典在32位系统上每个键值对使用45-80字节.同时,每对整数array.array('i')只使用8个字节,并且只需要一点记账,就可以实现一个相当快速的基于数组的int→int字典.
一旦你有一个int-int字典的内存效率实现,将你的字符串→(object,int,int)字典拆分成三个字典并使用散列而不是完整的字符串.你将获得一个int→object和两个int→int词典.按如下方式模拟int→对象字典:保留对象列表并将对象的索引存储为int→int字典的值.
我确实意识到要获得基于数组的字典需要相当多的编码.我遇到了类似于你的问题,我已经实现了一个相当快速,非常高效,通用的hash-int字典. 这是我的代码(BSD许可证).它是基于数组的(每对8个字节),它负责密钥散列和冲突检查,它在写入期间保持数组(实际上是几个较小的数组),并在读取时进行二进制搜索.您的代码简化为:
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)
Run Code Online (Sandbox Code Playgroud)
该checking参数指定发生冲突时会发生什么:在读取和写入时CHK_SHOUTING引发,CollisionError在读取时CHK_DELETING返回None并在写入时保持静默,CHK_IGNORING不进行冲突检查.
以下是我的实现的简要说明,欢迎优化提示!顶级数据结构是数组的常规字典.每个数组最多包含2^16 = 65536整数对(平方根2^32).键k和相应的值v都存储在k/65536-th数组中.数组按需初始化并按键排序.每次读写都执行二进制搜索.碰撞检查是一种选择.如果启用,则尝试覆盖已存在的密钥将从字典中删除密钥和关联值,将密钥添加到一组冲突密钥,并(再次,可选地)引发异常.