Linux Debugging (九) 一次生产环境下的“内存泄露”

简介:

一个偶然的机会,发现一个进程使用了超过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 rate is.

简单翻译一下,就是tcmalloc将内存交回OS的机制:默认情况下,tcmalloc会将长时间未用的内存交还系统。tcmalloc_release_rate这个flag控制了这个交回频率。你可以在运行时通过这个语句强制这个release发生:

 MallocExtension::instance()->ReleaseFreeMemory();

当然了,你可以通过 SetMemoryReleaseRate() 来设置这个tcmalloc_release_rate. 如果设置为0,代表永远不交回。数字越大代表交回的频率越大。一般合理的值就是设置一个0 - 10 之间的一个数。也可以通过设置环境变量 TCMALLOC_RELEASE_RATE来设置这个rate。

带着这个怀疑,首先还是通过Google's gpreftools 检查一下heap的使用情况:

1.  export HEAPCHECK=draconian

2.  export PPROF_PATH=/usr/local/bin/pprof

直接启动即可。

之所以设置为draconian,因为想得到更详细的统计信息。更将相信的解释如下:Flavors of Heap Checking


These are the legal values when running a whole-program heap check:

  1. minimal
  2. normal
  3. strict
  4. draconian

"Minimal" heap-checking starts as late as possible in a initialization, meaning you can leak some memory in your initialization routines (that run before main(), say), and not trigger a leak message. If you frequently (and purposefully) leak data in one-time global initializers, "minimal" mode is useful for you. Otherwise, you should avoid it for stricter modes.

"Normal" heap-checking tracks live objects and reports a leak for any data that is not reachable via a live object when the program exits.

"Strict" heap-checking is much like "normal" but has a few extra checks that memory isn't lost in global destructors. In particular, if you have a global variable that allocates memory during program execution, and then "forgets" about the memory in the global destructor (say, by setting the pointer to it to NULL) without freeing it, that will prompt a leak message in "strict" mode, though not in "normal" mode.

"Draconian" heap-checking is appropriate for those who like to be very precise about their memory management, and want the heap-checker to help them enforce it. In "draconian" mode, the heap-checker does not do "live object" checking at all, so it reports a leak unless all allocated memory is freed before program exit. (However, you can use IgnoreObject() to re-enable liveness-checking on an object-by-object basis.)

"Normal" mode, as the name implies, is the one used most often at Google. It's appropriate for everyday heap-checking use.

In addition, there are two other possible modes:

  • as-is
  • local

as-is is the most flexible mode; it allows you to specify the various knobs of the heap checker explicitly. local activates the explicit heap-check instrumentation, but does not turn on any whole-program leak checking.

但是很不幸,还是没有检查出来:



上面的泄露统计不是预期的,因为“泄露”了至少10G的内存了。

那么还是强制的释放不用的buffer吧:

MallocExtension::instance()->ReleaseFreeMemory();

问题解决了。
目录
相关文章
|
9月前
|
缓存 Linux
linux 手动释放内存
在 Linux 系统中,内存管理通常自动处理,但业务繁忙时缓存占用过多可能导致内存不足,影响性能。此时可在业务闲时手动释放内存。
418 17
|
5月前
|
缓存 Linux 数据安全/隐私保护
Linux环境下如何通过手动调用drop_caches命令释放内存
总的来说,记录住“drop_caches” 命令并理解其含义,可以让你在日常使用Linux的过程中更加娴熟和自如。
1021 23
|
7月前
|
监控 Linux Python
Linux系统资源管理:多角度查看内存使用情况。
要知道,透过内存管理的窗口,我们可以洞察到Linux系统运行的真实身姿,如同解剖学家透过微观镜,洞察生命的奥秘。记住,不要惧怕那些高深的命令和参数,他们只是你掌握系统"魔法棒"的钥匙,熟练掌握后,你就可以骄傲地说:Linux,我来了!
231 27
|
8月前
|
消息中间件 Linux
Linux中的System V通信标准--共享内存、消息队列以及信号量
希望本文能帮助您更好地理解和应用System V IPC机制,构建高效的Linux应用程序。
273 48
|
8月前
|
缓存 NoSQL Linux
Linux系统内存使用优化技巧
交换空间(Swap)的优化 禁用 Swap sudo swapoff -a 作用:这个命令会禁用系统中所有的 Swap 空间。swapoff 命令用于关闭 Swap 空间,-a 参数表示关闭 /etc/fstab 文件中配置的所有 Swap 空间。 使用场景:在高性能应用场景下,比如数据库服务器或高性能计算服务器,禁用 Swap 可以减少磁盘 I/O,提高系统性能。
292 3
|
8月前
|
缓存 Linux
Linux查看内存命令
1. free free命令是最常用的查看内存使用情况的命令。它显示系统的总内存、已使用内存、空闲内存和交换内存的总量。 free -h • -h 选项:以易读的格式(如GB、MB)显示内存大小。 输出示例: total used free shared buff/cache available Mem: 15Gi 4.7Gi 4.1Gi 288Mi 6.6Gi 9.9Gi Swap: 2.0Gi 0B 2.0Gi • to
575 2
|
9月前
|
消息中间件 Linux
Linux:进程间通信(共享内存详细讲解以及小项目使用和相关指令、消息队列、信号量)
通过上述讲解和代码示例,您可以理解和实现Linux系统中的进程间通信机制,包括共享内存、消息队列和信号量。这些机制在实际开发中非常重要,能够提高系统的并发处理能力和数据通信效率。希望本文能为您的学习和开发提供实用的指导和帮助。
619 20
|
10月前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
11月前
|
缓存 Ubuntu Linux
Linux环境下测试服务器的DDR5内存性能
通过使用 `memtester`和 `sysbench`等工具,可以有效地测试Linux环境下服务器的DDR5内存性能。这些工具不仅可以评估内存的读写速度,还可以检测内存中的潜在问题,帮助确保系统的稳定性和性能。通过合理配置和使用这些工具,系统管理员可以深入了解服务器内存的性能状况,为系统优化提供数据支持。
659 4
|
11月前
|
存储 算法 安全
深入理解Linux内核的内存管理机制
本文旨在深入探讨Linux操作系统内核的内存管理机制,包括其设计理念、实现方式以及优化策略。通过详细分析Linux内核如何处理物理内存和虚拟内存,揭示了其在高效利用系统资源方面的卓越性能。文章还讨论了内存管理中的关键概念如分页、交换空间和内存映射等,并解释了这些机制如何协同工作以提供稳定可靠的内存服务。此外,本文也探讨了最新的Linux版本中引入的一些内存管理改进,以及它们对系统性能的影响。