Data structures 对于小而简单的缓存,最好的数据结构是什么

Data structures 对于小而简单的缓存,最好的数据结构是什么,data-structures,coding-style,Data Structures,Coding Style,我通常需要相对较小的数据(一个不使用时间戳的非常简单的方法是,在最后有一个MRU(也就是说,当对同一对象的请求第二次出现时,删除它并在dict的末尾再次添加)因此,当需要过期时,如果大小大于限制,只需从有序dict的开头删除一个大小为X的片段 效率现在取决于有序dict的实现方式。我怀疑是否有解决这一问题的黄金子弹;最佳策略在很大程度上取决于缓存未命中的成本和计算参数的时间分布 垃圾收集方法可能会给您一些启示。如果您将缓存视为堆,并将缓存命中数视为引用,那么您就有了在命中数较低(而不是为零)的情

我通常需要相对较小的数据(一个不使用时间戳的非常简单的方法是,在最后有一个MRU(也就是说,当对同一对象的请求第二次出现时,删除它并在dict的末尾再次添加)因此,当需要过期时,如果大小大于限制,只需从有序dict的开头删除一个大小为X的片段


效率现在取决于有序dict的实现方式。

我怀疑是否有解决这一问题的黄金子弹;最佳策略在很大程度上取决于缓存未命中的成本和计算参数的时间分布

垃圾收集方法可能会给您一些启示。如果您将缓存视为堆,并将缓存命中数视为引用,那么您就有了在命中数较低(而不是为零)的情况下高效收集缓存结果的问题。这个问题比GC更容易理解,因为您所做的任何事情都可以重新计算


在这种情况下,对方法的改进是为频繁命中的参数引入一个额外的缓存。为每个缓存值添加一个计数器,该值在缓存命中时递增。当超过某个阈值时,缓存值将提升到额外的缓存。两代缓存都可以进行大小限制,因此您仍然有一个硬lim这是一个经验问题,如果(可能的)缓存未命中的减少证明了开销的合理性(在两个缓存中查找、命中计数器、复制等)…

您可以查看Java和LinkedHashSet以获得灵感。基本上,它维护了一个用于插入和可选访问顺序的双链接列表

要维护LRU,您可以定义在插入新条目时删除最旧条目(靠近linkedlist头部)的策略

cache = {}
def calculate_caches(parms):
    if parms not in cache:
        cache[parms] = calculate(parms)
    return cache[parms]
if len(cache) > 1000:
    cache = {}
cache = {}
def calculate_caches(parms):
    if parms not in cache:
        cache[parms] = (time.time(), calculate(parms))
    expire()
    return cache[parms][1]

def expire()
    if len(cache) > 1000:
        mintime = time.time()
        time2key = {}
        for key, (timestamp, val) in cache.items():
            mintime = min([mintime, timestamp])
            time2key[timestamp] = key
        if mintime in time2key:
            del cache[time2key[mintime]]