You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python 2.7中如何获取@ring.lru装饰静态方法的缓存统计?

解决方案:获取ring LRU缓存的统计数据(类似functools.lru_cache的cache_info)

我之前在Python 2.7里用ring库的时候也碰到过这个问题——明明知道内部在统计命中/未命中,但就是拿不到数据。下面给你几个实用的解决办法,从简单到稳妥都有:

方法1:直接访问ring缓存的内部统计属性

ring的LRU缓存实现里,存储实例(storage)有一个私有字典_stats,专门记录缓存的命中、未命中次数。你可以直接通过装饰后的函数对象访问它:

# 假设你的静态方法定义在某个类中,比如MyClass
class MyClass:
    @ring.lru()
    @staticmethod
    def get_hostname_by_id(object_id):
        return Monkey.get_single_monkey_by_id(object_id).hostname

# 获取缓存统计数据
cache_storage = MyClass.get_hostname_by_id.storage
hits = cache_storage._stats.get('hit', 0)
misses = cache_storage._stats.get('miss', 0)
total_calls = hits + misses

print "Cache hits: {}, misses: {}, total calls: {}".format(hits, misses, total_calls)

⚠️ 注意:这依赖于ring的内部实现细节(_stats私有属性),如果你的ring版本更新,这个属性可能会变化。我在ring 0.14.0(Python2.7支持的较新版本)里测试是有效的。

方法2:给缓存函数添加自定义的cache_info方法

为了用起来更像标准库的functools.lru_cache,可以给装饰后的方法加一个cache_info方法,返回结构化的统计数据:

class MyClass:
    @ring.lru()
    @staticmethod
    def get_hostname_by_id(object_id):
        return Monkey.get_single_monkey_by_id(object_id).hostname

# 定义cache_info方法,模仿标准库的格式
def cache_info():
    storage = MyClass.get_hostname_by_id.storage
    hits = storage._stats.get('hit', 0)
    misses = storage._stats.get('miss', 0)
    currsize = len(storage._cache)  # 当前缓存的条目数
    # 返回和functools.lru_cache.cache_info()类似的元组:(hits, misses, maxsize, currsize)
    return (hits, misses, storage.maxsize, currsize)

# 把方法绑定到缓存函数上
MyClass.get_hostname_by_id.cache_info = cache_info

# 调用方式和标准库完全一样:
info = MyClass.get_hostname_by_id.cache_info()
print "Hits: {}, Misses: {}, Max size: {}, Current size: {}".format(*info)

方法3:自己包装一层,不依赖ring内部实现

如果担心私有属性不稳定,你可以自己写一个简单的包装器,手动统计命中和未命中:

def track_cache_stats(cached_func):
    hits = [0]  # 用列表是因为Python2.7里闭包不能修改外部变量,列表是可变对象
    misses = [0]

    def wrapper(*args, **kwargs):
        # 先检查缓存键是否存在
        cache_key = cached_func._get_key(*args, **kwargs)
        if cached_func.storage.exists(cache_key):
            hits[0] += 1
        else:
            misses[0] += 1
        return cached_func(*args, **kwargs)

    def cache_info():
        return {
            'hits': hits[0],
            'misses': misses[0],
            'total_calls': hits[0] + misses[0],
            'current_size': len(cached_func.storage._cache)
        }

    wrapper.cache_info = cache_info
    return wrapper

# 使用方式:先装饰ring.lru,再用我们的跟踪器
class MyClass:
    @track_cache_stats
    @ring.lru()
    @staticmethod
    def get_hostname_by_id(object_id):
        return Monkey.get_single_monkey_by_id(object_id).hostname

# 调用统计
stats = MyClass.get_hostname_by_id.cache_info()
print "Cache stats: {}".format(stats)

这个方法完全不依赖ring的内部私有属性,通过_get_key生成缓存键,再用storage.exists判断是否命中,兼容性更好。

内容的提问来源于stack exchange,提问作者Shay Nehmad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:04:41