Nginx 假性内存泄露
Nginx在使用中,发现其使用的VSZ和RSS都在不断变大,查看新增的代码,没有找到内存泄露的地方,ngx_palloc和ngx_pfree都是对称调用的。
Nginx 内存池机制
使用Nginx开发过的都知道,在Nginx里面普遍使用ngx_palloc/ngx_pnalloc申请内存,其中入参有一个pool,它是从ngx_create_pool获得的一个对象,改函数入参指定了这个内存池的大小。
后续是 ngx_palloc/ngx_pnalloc从pool中申请内存均在这块大内存中申请内存,内存的分配机制非常简单,线性搜索可使用的内存大小块即可。
Nginx 内存池机制中的坑
如果 pool中大小一共1k,然后使用完了,接着从这个pool中申请内存会怎么样?Nginx不会返回失败,而是
(1):如果申请的内存大小,小于1k,则通过memalign申请一个1k pool2,挂在入参pool的链表后面,组成一个链表,然后接着从这个新pool2中申请内存。
(2):如果申请的内存大小,大于1k,则通过malloc申请一个指定大小的内存,挂在入参pool中,注意这块内存不会当做pool用,这块内存简单的返回给调用者。
所有这一切内存,都可以在ngx_destroy_pool中被释放,这是没问题的。但是,假设业务逻辑需要频繁申请内存,即频繁ngx_palloc,担心内存泄漏的人肯定会主动调用ngx_pfree希望立刻释放内存,但是实际上ngx_pfree毫无效果。
ngx_pfree只会释放(2)中的内存,而不会释放(1)中的内存。所以即使调用ngx_pfree,也无法减少Nginx在调用ngx_palloc中频繁增加的内存。
真碰到这种场景,只能使用ngx_alloc和ngx_free了,它们只是简单的封装了下glibc的malloc和free(当然gilbc的free也有类似不释放的问题,只是比Nginx造成的问题小多了)。
或者在适当的时候调用ngx_reset_pool,那内存池的内存使用情况初始化为0。
---------------------
作者:Mrpre
原文:https://blog.csdn.net/mrpre/article/details/85273831
版权声明:本文为博主原创文章,转载请附上博文链接!