背景
之前写过一篇文章 内存碎片分析
的后续分析。
问题
检查大厅状态时发现check服务虚拟内存很高,于是就看了下历史的内存状态
时间时从12月3日9:51分开始突然所有check服务都上升,然后12月4日7:01分提交内存下降,但虚拟内存仍然不变。
分析过程
1) 提交内存上升,必然是代码中大量申请内存导致,于是review了代码查看有没有大的内存申请,没有。
2)已经确认了上升时间,那么查看每小时的消息处理统计,有没有处理消息的量级上升,没有。
3)查看12月3日9:50~9:51之间的日志,无线索。
4)查看12月4日7:01~7:02之间的日志,有线索,count值很大。
1 | 12/04/19 07:02:28:955[4500][INFO][Server.cpp:770] release server buffer pool done. count = 408490. |
对比了历史日志的,大都是几百, 所以应该是这个时刻通讯库调用了 ReleaseSockBufPool()函数清理了无效buff导致提交内存大量释放。
review了底层通讯库的代码,如果报文突然大量涌入,会开辟很多buff,每个buff=4K,而且这个内存只能手动清理,无法自动清理。
然后去咨询运维,12月3日机房网络状况,那个时刻有个较大的网络抖动。
原因就是:
1)网络抖动导致通讯库瞬间大量申请内存;
2)第二天定时清理释放无效内存;
3)虚拟内存大小未变化。
虚拟内存大小未变化
我们的服务经常出现虚拟内存过高的问题,而这次checksvr确确实实也碰到了提交内存下降,但虚拟内存却不下降,特别的写了个demo,非调试下运行
1 | int _tmain(int argc, _TCHAR* argv[]) |
发现4K的内存申请,释放之后虚拟内存是不会下降的,4K一直调整到508K时,提交内存和虚拟内存都会同时下降;原因是内存大小>507K时,内存已经不在堆中申请,而是在堆外申请。
总结点
学习了,原来虚拟内存过高也不一定是内存碎片,也可能是某次提交内存的大量申请,然后释放从而导致虚拟内存上升。
通讯库4K的由于历史原因修复的风险很大,所以计划使用asio架构的通讯库替换原来老的库。