科普篇之Java堆内缓存优化-IntegerCache的使用
如果当堆内缓存中存在大量重复的Long或Integer(有限个且稠密的,如果不稠密需自己实现IntegerCache),我们首先想到的是能不能把Integer缓存到一个Map中,当Map中存在时就使用Map中的Integer,Map中不存在时就new一个Integer放进去,Long或Integer的cache所实现的功能
以直播场景为例,在直播推荐系统中,主播的状态是实时变化的,为了实时获取主播的实时状态,会对主播的直播画面进行截图进行ai识别,对主播打上一系列标签,比如唱歌,跳舞,静音,挂屏
对正在直播的主播每5s输出一次识别结果,一次识别结果中包含50多种标签,每个主播会缓存最近120个识别结果
假如在4000个主播正在直播,那么内存中就会存在4000*120*50=24000000,2千多万重复的主播标签id,而标签id在我们系统中要么是String,要么是Integer,对于String类型的我们可以用String.intern()优化,对于Integer类型的我们可以利用IntegerCache优化
IntegerCache默认是缓存-128~128的整型,ai识别结果最大为5091,需增加jvm启动参数-Djava.lang.Integer.IntegerCache.high=8192,并使用Integer.valueOf来获取Integer对象即可
在我们的场景中使用String.intern()和IntegerCache优化ai标签后通过对比垃圾回收后的内存占用,粗略估计减少了近4G的内存使用
优化前
优化后
观察字符串常量池,大小是动态变化的,运行时常量可被gc正常回收