【问题标题】:Balance between dictionary size and memory consumption字典大小和内存消耗之间的平衡
【发布时间】:2014-05-29 03:06:26
【问题描述】:

我正在使用memoized decorator 来缓存重复调用。由于对一些中等规模的测试用例进行记忆,我发现执行速度提高了 4 倍。

对于较大的测试用例,将输入映射到输出的记忆字典会占用大量内存,以至于我收到 "java.lang.OutOfMemoryError: Java heap space" 错误(我正在使用 Jython)。

我可以通过使用memoized_cache[hash(key)] = value 而不是memoized_cache[key]: value 来节省一些内存,假设hash(key) 的字节数比key 少。正如@gnibbler 所指出的,如果存在哈希冲突,这将导致问题。

我可以介绍的其他内存节省是将字典的大小限制为固定数量的项目。这样的SizedDict recipe 已经存在,但我想截断最不常访问的元素。

这是我写的:

from collections import Counter

class FrequencySizedDict(dict):
    def __init__(self, size=1000):
        dict.__init__(self)
        self._maxsize = size
        self._counter = Counter()
    def __getitem__(self, key):
        self._counter[key] += 1
        return dict.__getitem__(self, key)
    def resize(self, size):
        keys = list(self._counter.most_common(size))
        items = [(key, dict.__getitem__(self, key)) for key in keys]
        self.clear()
        dict.update(self, items)
    def __setitem__(self, key, value):
        if len(self._queue) >= self._maxsize:
            self.resize(self._maxsize/2)
        self._counter[key] += 1
        dict.__setitem__(self, key, value)

有没有更好的数据方式来实现这一点,同时减少内存或时间开销? resize 挺贵的:O(n log n)

【问题讨论】:

  • memoized_cache[hash(key)] 会在您有哈希冲突时引起有趣的错误。

标签: python algorithm memory data-structures dictionary


【解决方案1】:

使用functools.lru_cache

@functools.lru_cache(maxsize=128, typed=False)

装饰器用一个可保存最多 maxsize 最近调用的记忆可调用函数来包装函数。当使用相同的参数定期调用昂贵的或 I/O 绑定的函数时,它可以节省时间。

pylru,如答案memoization library for python 2.7中所述

【讨论】:

  • 这是 Python3.2+ 的最佳答案,不幸的是 Jython 还没有。
  • 糟糕,没有意识到这是 Py3 独有的功能。添加了指向应该与 Jython 一起使用的库的链接
  • 我真的在寻找一种最不常用的缓存算法,但这个答案让我走上了寻找什么的正确轨道。这个 LFU 实现看起来有点类似于我的原始代码:code.activestate.com/recipes/…,使用计数器来跟踪项目的访问频率。
猜你喜欢
  • 2017-10-07
  • 2014-11-25
  • 1970-01-01
  • 2017-02-07
  • 2019-09-14
  • 1970-01-01
  • 2015-04-04
  • 2016-08-25
  • 2011-02-20
相关资源
最近更新 更多