Nginx 假性内存泄露

Nginx 假性内存泄露

Nginx在使用中,发现其使用的VSZRSS都在不断变大,查看新增的代码,没有找到内存泄露的地方,ngx_pallocngx_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_allocngx_free了,它们只是简单的封装了下glibc的mallocfree(当然glibc的free也有类似不释放的问题,只是比Nginx造成的问题小多了)。
或者在适当的时候调用ngx_reset_pool,即重置内存池。注意ngx_reset_pool只是重置,即把pool中内存的偏移全部重置,而不是释放内存,偏移重置后,这块内存又能被调用者申请到,而不会因为pool中内存不够而频繁的触发(1)或者(2)。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值