按文档描述的条件测试小整数共享池,用OBJECT REFCOUNT和10万key的内存对比两种独立证据,验证这个优化在本机的Redis版本里是否还在生效。
Redis历史上有一个广为人知的优化:0~9999的小整数会被预先创建好,多个key指向同一个共享对象。
操作,按文档描述的生效条件CONFIG GET maxmemory → :0(满足共享条件) CONFIG GET maxmemory-policy → :noeviction(满足共享条件) SET z1 42 SET z2 42 OBJECT REFCOUNT z1
如果真的共享,REFCOUNT应该是一个很大的数字(表示很多key在引用同一个对象)。
结果SET z1 42 SET z2 42 OBJECT ENCODING z1 → :int(满足能被共享的编码条件) OBJECT REFCOUNT z1 → :1 OBJECT REFCOUNT z2 → :1 DEBUG OBJECT z1 → refcount:1 encoding:int ...
不管用 OBJECT REFCOUNT 还是更底层的 DEBUG OBJECT,两个key(z1、z2)都各自显示引用计数为1,完全没有"共享同一个对象"该有的巨大计数。这跟很多资料里描述的老版本Redis行为对不上。
如果共享真的存在,10万个key全设成同一个小整数,应该比10万个各不相同的大整数省下大量内存。
结果10万个key全部SET成同一个可共享的小整数(42): DBSIZE → 100000 used_memory → :6362048 字节 10万个key各自SET成不重复的随机大整数(不可共享): DBSIZE → 100000 used_memory → :6362416 字节 两者只差368字节,几乎没有差别!
如果小整数对象真的被10万个key共享,"全部指向同一个42"的内存占用应该远小于"10万个各不相同的大数字"(前者理论上只需要一份对象+10万个指针,后者需要10万份完整对象)。测出来的结果是:两者几乎一模一样——这从内存证据的角度,独立确认了 OBJECT REFCOUNT 显示的现象:这个的Redis 8.10.1实例里,小整数共享池没有观察到在生效。
每一步都是本文上面用redis-cli和Python脚本跑出来的原始结果。
OBJECT REFCOUNT / DEBUG OBJECT:检查引用计数pipeline:批量写入10万个key做内存对比