-
Author:Echo Chen(陈斌)
-
Email:chenb19870707@gmail.com
-
Date:Jan.27th, 2015
最近游戏已上线运营,进行服务器内存优化,发现一个非常奇妙的问题,我们的认证服务器(AuthServer)负责跟第三方渠道SDK打交道(登陆和充值),由于采用了curl阻塞的方式,所以这里开了128个线程,奇怪的是每次刚启动的时候占用的虚拟内存在2.3G,然后每次处理消息就增加64M,增加到4.4G就不再增加了,由于我们采用预分配的方式,在线程内部根本没有大块分内存,那么这些内存到底是从哪来的呢?让人百思不得其解。
1.探索
一开始首先排除掉内存泄露,不可能每次都泄露64M内存这么巧合,为了证明我的观点,首先,我使用了valgrind。
1: valgrind --leak-check=full --track-fds=yes --log-file=./AuthServer.vlog &
然后启动测试,跑至内存不再增加,果然valgrind显示没有任何内存泄露。反复试验了很多次,结果都是这样。
在多次使用valgrind无果以后,我开始怀疑程序内部是不是用到mmap之类的调用,于是使用strace对mmap,brk等系统函数的检测:
1: strace -f -e"brk,mmap,munmap" -p $(pidof AuthServer)
其结果如下:
1: [pid 19343] mmap(NULL, 134217728, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7f53c8ca90002: [pid 19343] munmap(0x7f53c8ca9000, 53833728) = 03: [pid 19343] munmap(0x7f53d0000000, 13275136) = 04: [pid 19343] mmap(NULL, 8392704, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f53d04a80005: Process 19495 attached
我检查了一下trace文件也没有发现大量内存mmap动作,即便是brk动作引起的内存增长也不大。于是感觉人生都没有方向了,然后怀疑是不是文件缓存把虚拟内存占掉了,注释掉了代码中所有读写日志的代码,虚拟内存依然增加,排除了这个可能。
2.灵光一现
后来,我开始减少thread的数量开始测试,在测试的时候偶然发现一个很奇怪的现象。那就是如果进程创建了一个线程并且在该线程内分配一个很小的内存1k,整个进程虚拟内存立马增加64M,然后再分配,内存就不增加了。测试代码如下:

本文作者在排查服务器内存优化问题时,发现一个现象:每当创建线程并分配小量内存时,虚拟内存会增加64M。经过一系列探索,发现是glibc的malloc机制在多线程环境下为了性能而使用arena内存池导致的。每个arena默认为64M,可通过设置环境变量限制arena数量,以减少不必要的内存占用。作者还提到,新版glibc的设计可能受到了tcmalloc的影响。
最低0.47元/天 解锁文章
2万+

被折叠的 条评论
为什么被折叠?



