A-A+

高性能编程需要注意大内存申请

2015年05月26日 Programming 评论 1 条

之前遇到一个问题,一个没有更新过代码的CACHE类server部署在新的机器上跑,请求量在1W次的时候,CPU使用率30%左右,内存充足,IO很轻,基本没有,但load值高达200多,导致cache server出现比较多的超过500ms的请求,影响服务。而正常机器,请求在5,6W次,由于是全内存型server,所以load只有1不到。
和一些同事一起定位问题,最终发现,由于是300个线程在执行,strace这些线程,发现只有4个操作在循环执行,mmap, read,read,munmap,但正常机器,则没有这样的mmap munmap调用表现表现。

  void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

请求中的addr 为null, len为1M,fildes为 -1。

怀疑是这里的反复mmap,申请大于1M内存,导致了线程阻塞,性能下降,load偏高。

同事检查代码后,发现确实有一块server中的循环中,有一个new内存的地方,定义的MAX_LENTH = 1024*1024,所以对这里进行了优化,将new放到了循环外面。再次上线压力测试,服务恢复正常。

代码没有变化,为什么新的server会出现这样的情况呢,为什么,晚上回来考虑,可能和申请大内存有关,所以我写了如下的简单代码测试了一下:

#include
#include
#include
int main(int argc, char ** argv)
{
if(argc != 2){
printf("please use ./test \n");
return 0;
}
for(int i =1; i< 1024 ; i++){ char * ptr = new char[1024*i]; //不断增大内存申请,看什么时候出现mmap usleep(atoi(argv[1])*1000); //换算成豪秒sleep,以便来的急查看strace的结果。 delete [] ptr; } return 0; }

执行的strace结果如下:

执行trace的结果

可以看到,mmap第一次出现的时候,申请的内存大小为139264,大概100多K, 可以看出,系统在申请小块内存和大块内存的时候,策略不同。所以我们的服务在不断的循环申请1M大内存中,不断的调用mmap系统调用,导致了对性能的影响。所以现在基本明确了原因,要不就是代码在过程中有过内存大小申请的调整,要不就是新就机器在这个多大内存使用mmap申请的数值上有不同,只需要简单用如上代码测试即可知道。而这里的解决方案,即可以把它放到循环中去,也可以减少内存的申请,在100K以内。

补充一下,后来测试了一下不同的机型,2.6的内核,都是在139264(132K+4096字节,4096字节是mmap调用时候,比用户申请的值多申请的一个常值)这个值的时候,开始使用mmap申请内存,可以看到,申请超过132K的内存时,会导致通过mmap的方式申请。 可能是系统没有连续的大内存块,通过了mmap的方式从堆上申请。而不同机器环境不同,可能这个值会有差异导致偶发。

原创文章,转载请注明: 转载自腾讯游戏DBA团队

本文链接地址: 高性能编程需要注意大内存申请

文章的脚注信息由WordPress的wp-posturl插件自动生成

标签:
Copyright © 腾讯游戏DBA团队 保留所有权利.  

用户登录

分享到: