各位朋友们大家好,有个内存方面的问题想听取您的意见,场景是这样的:
系统是个网站,tomcat负责一些ajax请求的响应,每个ajax响应的代码中都要向监控系统上报一个属性,例如有个查询的ajax接口,对应的代码中有一段:sendAttr(19001);------这段代码里面的内容是向监控系统的ip和端口发送一个很简单的udp包,内容除了固定的包头还有19001的十六进制数据。
目前19001这样的属性大约有300个,sendAttr方法每天的调用次总数大约在50万次左右,
sendAttr方法里面发送udp包需要准备byte数组,50万次的调用自然不适合每次都去new一个数组,目前是一个静态的HashMap<Integer,byte[]>,根据19001这样的id保存对应的数组,这样每次发送的时候从map中取出来就可以直接发送了。
我的问题是想和大家讨论一下理论上sendAttr方法是否还有优化的空间:
虽然使用了HashMap可以避免每次都去new数组,但是这些数组应该是存在堆内存中的吧,经过数次YGC后能到老年代去(如果理解有误请指正,谢谢了),每次FGC的时候还是会被扫描。
我想做一个简单的工具,输入19001,19002这些int型数字,输出一个java文件,里面是多个数组的定义,例如:
private static final byte[] b_19001 = {0x0c,0x00,.....};
private static final byte[] b_19002 = {0x0c,0x00,.....};
把这个文件加入工程,sendAttr中使用这些数组,系统启动后,这些数组就能放到方法区里面去了,这样只要方法区够大就不会有问题,这些对象就和堆的GC没有关系了。
这样的改法未必能提升性能,但是我想请教各位大神们这个方向是否正确,即:将一些固定的数据想办法放到方法区,减少GC涉及的对象数量,提升性能。
我只能说感觉还行,但是imfunny说的比你的更好。可以提取
有一点小的疑问:既然你这个数组可以是final的,是不是意味着这300个属性值是不会去更新,每次查询返回固定值呢?
如果是的话,是不是可以把这个静态属性区域,在客户端初始化的时候,就放置在客户端呢,这样,就不用每次查询的时候,都做一次服务器的交互了。
如果不是的话,感觉在服务器端做一个对这些属性的缓存池比较好。
@在大地画满窗子,谢谢你的回复。
监控系统是个公共的系统,这三百个属性值是固定的。之所以每次都要做交互是为了做监控的需要,例如用户每次点击查询按钮,我们的系统都会向监控系统发一次UDP包,这样就能在监控系统看到查询量的曲线图了,所以只能实时去发,不然如果突然系统宕机,请求量掉零的话,监控系统就不能及时告警了。
还有你说的在服务器对这些属性做缓存,也不好实现,因为那是个公司级别的大型监控系统,只接收我们发UDP包过去,我们的系统相对来说也只是一个用户而已,只能遵守规则。
@zq2599: 哦,是这样一个关系啊。
你的方案,我觉得挺好的