共计 1646 个字符,预计需要花费 5 分钟才能阅读完成。
问题定位:
最近奉命解决游戏中始终在的内存不够的问题,最终定位到底层的缓存机制应用的是 google 提供的 ConcurrentLinkedHashMap 做数据缓存的。
简略介绍下 ConcurrentLinkedHashMap,这是一个基于 LRU 策略的缓存,说白了就是热点数据缓存,反对设置最大缓存个数,监控到缓存数量超过最大值后会根据权重策略让数据过期。
剖析:
依据 ConcurrentLinkedHashMap 的个性,咱们这边揣测出玩家数据在被加载放到缓存后,如果缓存没有超过设置的最大值,则这些数据会始终放在缓存中;正当上来说这些没被应用的数据,在闲暇肯定工夫后是能够被革除的,而不必始终占据在缓存中。
然而 ConcurrentLinkedHashMap 并没有在数据闲暇肯定工夫后主动清空数据的机制,因此想要解决这个缓存问题,必须应用一个既反对基于缓存个数大小回收,又反对基于闲暇工夫回收的第三方组件,而在多番理解和数据查证后最终抉择了 Caffeine。
Caffeine 是什么
Caffeine 是一个高性能的 Java 缓存库,缓存和 Map 之间的一个基本区别在于缓存能够依据回收策略回收存储的数据。此策略间接影响缓存的命中率,而缓存命中率额也是缓存库的一个重要特色。Caffeine 因应用 Window TinyLfu 回收策略,提供了一个近乎最佳的命中率。
咱们能够看到官网提供的几张性能截图
场景 1:8 个线程读,100% 的读操作
image-20201101101125396
场景二:6 个线程读,2 个线程写,也就是 75% 的读操作,25% 的写操作
image-20201101101157144
场景三:8 个线程写,100% 的写操作
image-20201101101219341
能够分明的看到 Caffeine 效率显著的高于其余缓存。
将 Caffeine 替换掉 ConcurrentLinkedHashMap,接下来就是要验证下,是否反对基于闲暇工夫回收,进而解决咱们游戏中的内存问题了。
Caffeine 和 ConcurrentLinkedHashMap 的应用比照
操作流程:本地起两个服,一个缓存底层应用的是 ConcurrentLinkedHashMap,另一个底层应用的是 Caffeine,Caffeine 服设置的数据操作闲暇工夫是 1 分钟,起服后别离应用 jvisualvm 记录起始内存曲线,截图保留,之后启动 2000 个机器人模仿登陆,登陆后再过 1 分钟别离手动调用 FullGC,查看 jvisualvm 记录的内存曲线,并查看堆 dump 记录。
【ConcurrentLinkedHashMap 服】起始内存
image-20201101103752470
【ConcurrentLinkedHashMap 服】2000 个机器人模仿登陆后下线,并手动调用 FullGC 后查看内存曲线
image-20201101104016330
咱们能够看到堆内存并没有回到原来的曲线。
查看堆 dump 记录
image-20201101104341454
能够看到该对象的实例数没有降落到 0。
【Caffeine 服】起始内存
image-20201101105100049
【Caffeine 服】2000 个机器人模仿登陆后下线,并手动调用 FullGC 后查看内存曲线
image-20201101105137160
这里看到内存曲线回到了起服时的模样,再查看堆 dump 记录
image-20201101104640103
能够看到,对象实例个数也被回收了,那么这里残余的实例个数 1 是怎么回事,这里波及到 Caffeine 的原理,留个悬念,等下篇文章再解说,有趣味关注一波,前期筹备写个 Caffeine 系列教程。
通过以上比照,能够得出 Caffeine 具备“主动”清空缓存过期数据的机制,并且能够解决咱们游戏中始终存在的内存问题。
总结
目前对 Caffeine 的替换曾经提交到线上运行了,因为目前网上相干教程偏少,因此后续筹备写一系列 Caffeine 相干的文章进行解密,有趣味的关注一波。
img