标签:
最近游戏在腾讯平台上线,已经快破200组,以前是一台机器可能就放一两组游戏区内存绰绰有余,只要没发生内存泄漏,也就没去关心。
但现在为了节约成本,我们会尽量一台虚拟机上放尽量多的游戏区。所以我们默认放了4个区(每个区占用6G,共24G),还有放了logger 服,gate,flash,redis等应用,
发现只要服务器维护后快一星期左右,内存占用从原先的10几个G一路高歌猛进,直到占满内存 95%+,经常性收到监控邮件,内存又不足了,甚至引发OOM killer。
为什么人数这么少了,内存占用还是会达到6G+,垃圾回收怎么没任何作用?
原因是因为即使JVM 从系统中申请来内存后,就不会再归还给系统,向系统交还内存和申请内存都是比较耗时的,或者说,JVM和操作系统之间的通信是比较昂贵的,从另外一个角度来看, 如果JVM一有空闲内存就交给操作系统的话,那必然会存在内存紧张,需要频繁的向操作系统申请内存,现有的做法都是向操作系统申请一大块内存,自己管理,从而避免了频繁的操作系统调用,并且能使用适合自身应用场景,特殊的内存管理方式来提高性能。
所以被JVM GC掉和内存返回给操作系统是两码事,被GC掉只是不占用java heap的空间,JVM会保留该空间给后续对象分配,不会返回给系统,即使是C语言也是这样,malloc分配空间后直接free,空间也不会返回,因为应用有很大的可能继续要求分配空间,绝大部分的实现会保留free 后的内存空间。
如果真想回收给系统也是做到的,JVM有个参数决定空闲堆内存大于一定百分比时才会把内存交还给操作系统,慎用!
想想原因也很简单,如1台24G内存的CVM,每个区我们一开始会分配6G的JVM堆栈空间(xmn,xmx=6g), 懂的人知道,这个JVM一直跑着,会消耗掉6G+的内存占用。但游戏到了第二天后其实也就单区200~300左右在线,完全没必要分配这么多的内存,3G已然足够,但我们又不可能去停机维护修改堆内存占用。所以我们可以在每次维护的时候调整内存占用,于是我给出了个3/8公式,聪明的运维同学帮忙做了脚本实现:
当然了,我们还可以对平均在线,最高在线分配不同的权重去获取应该分配的内存,
这样,内存占用高的问题就基本解决了,资源成本省下了许多。
标签:
原文地址:http://blog.csdn.net/jiangguilong2000/article/details/44523555