一个偶然的机会,发现一个进程使用了超过14G的内存。这个进程是一个RPC server,只是作为中转,绝对不应该使用这么多内存的。即使并发量太多,存在内存中的数据太多,那么在并发减少的情况下,这个内存使用肯定会降下来。但是事实上,这个内存会一直涨,直到被OOM Killer杀掉。
由于这个rpc server的逻辑比较简单,先走读源码,除了发现一些简单的编程上面的问题外,没有大的问题。先上valgrind:
valgrind --tool=memcheck --leak-check=full -v ./rpc_server
原来的情况是,一般都会检查出内存泄露的。这次没有(否则也不会有本文了):
实际上至少10G的“内存泄露”。既然没有检查出,说明这些内存还是活着的。设想一下这个场景:每个请求都new一块内存,放到一个列表中。正常的话请求处理完需要从这个列表中删除这块内存。如果没有删除,那么这就算是内存泄露。但是valgrind检查不出来。
由于上面这个进程使用了tcmalloc,是不是tcmalloc的问题?我们知道tcmalloc的效率要优于malloc,那么是不是tcmalloc的问题,如果它一直申请内存,不释放,就会造成这种”内存泄露“。注意下面一段话:
Releasing Memory Back to the System
By default, tcmalloc will release no-longer-used memory back to the kernel gradually,
over time.
The tcmalloc_release_rate flag controls how quickly this happens.
You can also force a release at a given point in the progam execution like so:
MallocExtension::instance()->ReleaseFreeMemory();
You can also call SetMemoryReleaseRate() to change the tcmalloc_release_rate value
at runtime, or GetMemoryReleaseRate to see what the current release