加载导致内存峰值的字典对象

Abi*_*d A 5 python django

我有一个字典对象,有大约60,000个密钥,我在我的Django视图中缓存和访问.该视图提供了基本的搜索功能,我在字典中查找搜索词,如下所示:

projects_map = cache.get('projects_map')
projects_map.get('search term')
Run Code Online (Sandbox Code Playgroud)

然而,只是抓住缓存的对象(在第1行)会导致服务器上的内存使用率大幅增加 - 有时超过100MB - 即使在返回值并呈现模板后内存也不会释放.

我怎样才能让记忆像这样抬起来?此外,我尝试在获取值后显式删除对象,但即使这样也不会释放内存峰值.

任何帮助是极大的赞赏.

更新:解决方案我最终实施

我决定实现自己的索引表,在其中存储密钥及其pi​​ckle值.现在,get()我使用:而不是在字典上使用:

ProjectsIndex.objects.get(index_key=<search term>)

并取消价值.这似乎解决了内存问题,因为我不再将巨型对象加载到内存中.它为页面添加了另一个小查询,但这就是它.似乎是一个完美的解决方案......现在.

red*_*dow 4

..使用一些适当的服务进行缓存怎么样,例如redismemcached,而不是在内存python端加载大对象?这样,如果字典增长得更多,您甚至可以在额外的机器上进行扩展。

无论如何,100MB内存包含所有数据+哈希索引+杂项。高架; 前几天我注意到自己,很多时候内存不会被释放,直到你退出Python进程(我从Python解释器填满了几GB内存,加载了一个巨大的json对象..:));如果有人有解决方案,那就很有趣了..

更新:用很少的内存进行缓存

仅 512MB 内存的您的选择是:

  • 使用redis,看看这里http://redis.io/topics/memory-optimization(但我怀疑512MB还不够,甚至优化)
  • 使用单独的机器(或集群,因为 memcached 和 redis 都支持分片)和更多的 RAM 来保留缓存
  • 使用数据库缓存后端,速度慢得多,但内存消耗更少,因为它将所有内容保存在磁盘上
  • 使用文件系统缓存(尽管我不认为比数据库缓存更喜欢这个)

并且,在后两种情况下,请尝试拆分对象,以便您永远不会立即从缓存中检索兆字节的对象。

更新:跨越多个缓存键的惰性字典

你可以用这样的东西替换你的缓存字典;这样,您可以像处理普通字典一样继续处理它,但只有当您真正需要数据时才会从缓存中加载数据。

from django.core.cache import cache
from UserDict import DictMixin

class LazyCachedDict(DictMixin):
    def __init__(self, key_prefix):
        self.key_prefix = key_prefix

    def __getitem__(self, name):
        return cache.get('%s:%s' % (self.key_prefix, name))

    def __setitem__(self, name, value):
        return cache.set('%s:%s' % (self.key_prefix, name), value)

    def __delitem__(self, name):
        return cache.delete('%s:%s' % (self.key_prefix, name))

    def has_key(self, name):
        return cache.has_key(name)

    def keys():
        ## Just fill the gap, as the cache object doesn't provide
        ## a method to list cache keys..
        return []
Run Code Online (Sandbox Code Playgroud)

然后替换这个:

projects_map = cache.get('projects_map')
projects_map.get('search term')
Run Code Online (Sandbox Code Playgroud)

和:

projects_map = LazyCachedDict('projects_map')
projects_map.get('search term')
Run Code Online (Sandbox Code Playgroud)