内存碎片分析(2)

背景

之前写过一篇文章 内存碎片分析

的后续分析。

问题

检查大厅状态时发现check服务虚拟内存很高,于是就看了下历史的内存状态

upload successful

时间时从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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int _tmain(int argc, _TCHAR* argv[])
{
std::list<char *> oList;
for (auto i = 0; i < 400000; i++)
{
char *pBuff = (char*)malloc(1024* 4 );
oList.push_back(pBuff);
}

for each (auto obj in oList)
{
free(obj);
}

system("pause");
return 0;
}

发现4K的内存申请,释放之后虚拟内存是不会下降的,4K一直调整到508K时,提交内存和虚拟内存都会同时下降;原因是内存大小>507K时,内存已经不在堆中申请,而是在堆外申请。

总结点

学习了,原来虚拟内存过高也不一定是内存碎片,也可能是某次提交内存的大量申请,然后释放从而导致虚拟内存上升。

通讯库4K的由于历史原因修复的风险很大,所以计划使用asio架构的通讯库替换原来老的库。