如何获取Python中lru_cache装饰类方法的缓存内存占用字节数
追踪lru_cache装饰的类方法的内存占用
你已经可以通过cache_info()获取被lru_cache装饰的类方法的调用统计(命中数、未命中数等),但需要一种类似sys.getsizeof()的方式,提取缓存占用的字节大小。
实现方案
lru_cache的缓存数据实际存储在被装饰方法的__cache__属性(部分Python版本为_cache)中,这是一个字典结构,键为调用方法时的参数元组(包含实例对象和传入参数),值为方法的返回结果。
要计算缓存的总内存占用,需要递归统计字典中所有键值对及其嵌套对象的大小(因为sys.getsizeof()仅返回对象本身的大小,不包含其引用的嵌套对象)。
示例代码
import sys from functools import lru_cache def get_total_size(obj, seen=None): # 递归计算对象的总内存占用,包含所有嵌套对象 seen = seen or set() obj_id = id(obj) if obj_id in seen: return 0 # 避免重复计算同一对象 seen.add(obj_id) size = sys.getsizeof(obj) # 处理常见容器类型 if isinstance(obj, (list, tuple, set, frozenset)): size += sum(get_total_size(item, seen) for item in obj) elif isinstance(obj, dict): size += sum(get_total_size(k, seen) + get_total_size(v, seen) for k, v in obj.items()) # 处理自定义对象的属性 elif hasattr(obj, '__dict__'): size += get_total_size(obj.__dict__, seen) return size class Exponent: def __init__(self, base): self.base = base @lru_cache(maxsize=None) def __call__(self, exponent): return self.base ** exponent # 测试流程 exponent_base_two = Exponent(2) exponent_base_two(2) exponent_base_two(3) # 输出缓存调用统计 print(f"缓存调用统计: {exponent_base_two.__call__.cache_info()}") # 计算并输出缓存总字节大小 cache = exponent_base_two.__call__.__cache__ total_cache_size = get_total_size(cache) print(f"缓存总字节大小: {total_cache_size}")
说明
get_total_size函数会遍历对象的所有嵌套结构,确保统计到缓存中所有数据的实际内存占用- 如果运行时提示
__cache__不存在,可尝试替换为_cache(部分Python版本的私有属性命名差异) - 统计结果包含缓存字典本身、所有参数元组、返回值对象及其内部引用的所有数据的总字节数
内容的提问来源于stack exchange,提问作者itamar kanter
相关产品推荐
相关产品推荐

