We can reproduce the problem with following standalone snippet.
Use tool smem to monitor the RSS: smem -P "a\.out", we will see
- with the "#if 1", memory cannot be reclaimed quickly, while
- with the "#if 0", memory can be reclaimed quickly.
I'm investigating the problem.
Thanks
Shuxin
Code to reproduce the problem
--------------------------------------------------------------
#include <strings.h>
static char** p = NULL;
static int array_sz = 4096;
static void
myalloc() {
int i;
p = (char** )malloc(sizeof(char*) * array_sz);
fprintf(stderr, "%p\n", p);
for (i = 0; i < array_sz; i++) {
p[i] = (char*)malloc(127 * 1024);
fprintf(stderr, "%p\n", p[i]);
}
}
static void
myfree() {
if (p) {
int i;
for (i = 0; i < array_sz; i++) {
free(p[i]);
}
free(p);
}
p = NULL;
}
int
main (int argc, char** argv) {
char c;
#if 1
if (mmap(sbrk(0), 1, PROT_READ|PROT_WRITE,
MAP_32BIT|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0) == MAP_FAILED) {
perror("mmap");
return -1;
}
#endif
while ((c = fgetc(stdin)) != 'q') {
if (c == 'a') {
myalloc();
continue;
}
if (c == 'f') {
myfree();
}
}
return 0;
}
---------------------------------------------------------------------------
On 08/25/2016 01:07 PM, Yichun Zhang (agentzh) wrote:
Hello!
2016-08-25 1:18 GMT-07:00 Peng Fang:
刚刚分别验证了刚发布的openresty-1.11.2.1和nginx-1.11.2,也是这个情况,即均只启动--with-http_mp4_module,均只访问一个开启mp4指令的location,仍然是openresty在访问后内存不下去,nginx-1.11.2在访问后内存迅速下去了,两个火焰图分别在附件里。
从你提供的内存泄漏火焰图上看,并不存在泄漏。二者的代码路径是完全相同的。
这里的原因应该是启用 ngx_lua 模块时,会强制 glibc 的 malloc 使用 mmap 来分配内存,而不是 sbrk
这样的系统调用在 data segment 里面分配,目的是为了把低 2GB 的内存地址空间都预留给 LuaJIT 的 GC
来使用。glibc 对于 mmap 分配的块可能会更加激进地缓存 free
掉的内存页。所以你看到的所谓的“不释放”其实并不是应用程序不释放,而只是 glibc 这样的基础系统库缓存了起来。
为进一步确认这一点,你可以持续无限制地保持压力,然后观察 nginx worker 进程的 RSS 是否会无限增长。
Regards,
-agentzh