程序在一个月的运行中不断吃内存,一个月吃掉了32G的内存,但是线上系统还不能停,不能改配置。。。。 有什么好办法排除内存泄露的问题么?
1
linxy 2015-07-29 20:01:45 +08:00
换go
|
2
matthewgao OP @linxy 不现实。。。
|
3
acros 2015-07-29 20:11:43 +08:00
占个座位等解答。
这种环境下,是不是只能靠内存dump分析了? |
4
fo2w 2015-07-29 20:15:32 +08:00
看描述我完全不知道你是要解决问题还是排查问题
不停机不能改配置要解决问题那无解, 或者我太废柴暂时没想到办法 要查问题这种情况下钩子就好了 但是...我还是建议好好review一遍代码... 这种泄漏量肉眼我真不信看不出来 |
5
sinxccc 2015-07-29 20:16:13 +08:00
我们常用的做法是首先复制一个尽可能跟在线系统一样的环境,然后如果性能说得过去的话用 valgrind 跑可疑进程,对性能要求高的话,加上自己包装过的 new/delete/malloc/free 然后跑一段时间看输出的统计。
分离出最可疑的地方之后再按照这个特征走查代码。 |
6
lijianying10 2015-07-29 20:20:45 +08:00 1
不知道是何种业务,
1. 取一份程序拷贝准备复现问题 2. 两个方面来确定问题的来源 1. 用更高的业务访问频率(业务参数)来模拟在线程序的情况,让问题显现更清楚 2. 满足上面一条之后,(如果是巨大循环的算法)每次注释掉一个模块,来排查问题。找到是那个大模块之后,再从大模块入手使用同样方法,直到找到泄露点。 1. 尽量避免注释掉依赖模块。从底层开始。 2. 模块的划分粒度大小很重要,影响排查速度 3. 如果是由独立业务堆砌出来的大型程序,要从业务划分来找到一个或者多个业务发生泄露,然后使用上面的方法 4. 如果十分确定使用上面两条找不到。最后一招CodeReview。 5. 找到来源之后修复一下,做项目回归测试。 希望此流程能帮到楼主。这也是我在做计算程序的时候排查泄露时候的方法。 |
7
ch3n2k 2015-07-29 20:32:34 +08:00
加大swap,让它泄漏去。话说什么程序不能停机啊?要改架构啊
|
8
typcn 2015-07-29 20:42:31 +08:00
|
9
zhouc 2015-07-29 22:03:47 +08:00
你们的程序是server程序,不能load balance traffic?
|
10
jedihy 2015-07-29 22:16:44 +08:00 via iPhone
对,valgrind,差不多就这些办法。一般单元测试的时候就要按模块找出内存泄露,不然耦合到一起很难找了。
|
11
lsmgeb89 2015-07-29 22:25:29 +08:00
大型的 C/C++ 程序,一开始开始就要考虑到内存管理模块啊,团队要制定好内存使用的规则,这样出现内存泄漏就可以定位到那个 instance 和代码位置。
PS:用 Valgrind 跑很慢的,而且不一定能够定位的。 |
12
xylophone21 2015-07-29 22:38:08 +08:00 1
#define new(x) mynew(__FILE__,__LINE__,x);
|
13
signifox 2015-07-29 23:32:04 +08:00
gcc4.8以上版本用[AddressSanitizer]{https://code.google.com/p/address-sanitizer/wiki/AddressSanitizer},
低版本的用[efence]{https://directory.fsf.org/wiki/Electric_Fence} 检查C++内存泄露的神器。 |
14
alphonsez 2015-07-30 00:07:20 +08:00
建议改成能重启的。老不能重启总是个麻烦,总不见得永远不部署吧?如果能重启就好办了,每天重启一次呗。
|
15
akira 2015-07-30 00:59:37 +08:00
如果有完善的日志的话,可以试试从日志里分析出业务量变化和内存增加变化的关系。定位到业务的话 就比较好做代码review了
|
16
dndx 2015-07-30 01:07:21 +08:00 via iPhone
用智能指针。
|
17
JamesRuan 2015-07-30 02:01:11 +08:00
上Erlang/OTP
|
18
vietor 2015-07-30 08:16:50 +08:00 via Android
所有内存分配回收代码都过一遍, 尤其用指针封装的地方(智能指针,共享指针),许多人没理解就乱用,用错。我之前就将所有智能指针转成自写封装类,解决内存泄漏
|
19
nightv2 2015-07-30 09:43:08 +08:00
重启啊,至少能改善问题,然后排查是那个模块
|
20
qyz0123321 2015-07-30 09:50:33 +08:00
智能指针是王道
|
21
eliteYang 2015-07-30 10:13:16 +08:00
强烈推荐intel vtunes分析,或者全局用智能指针,或者全局排查指针申请和释放的地方,看看有没有因为什么情况导致申请完后一些条件不满足,没有走到释放
|
22
hitmanx 2015-07-30 10:30:42 +08:00
生产环境不能停机的话,可以开发环境重新跑一次,并打开valgrind\address sanitizer之类的工具在运行时检测一下内存泄露。如果这也不行的话,可以上一些静态代码分析工具看看,比如coverity之类的
|
23
acgeo 2015-07-30 11:25:18 +08:00
楼上各位说得都是扯犊子的~~
这种情况,吃内存是无法避免的~ 写个shell脚本 定时执行~ 这样每次执行完毕,进程结束会自动释放掉内存. |
24
pp3182429 2015-07-30 13:29:40 +08:00
以前每次都是check所有分配内存的地方,是不是释放了…找所有的new和malloc==#。。
|
25
acgeo 2015-07-30 15:54:28 +08:00
楼上各位说得都是扯犊子的~~
这种情况,吃内存是无法避免的~ 写个shell脚本 定时执行~ 这样每次执行完毕,进程结束会自动释放掉内存. |
26
linux40 2015-07-30 16:27:50 +08:00
为什么不用标准库里的模板?虽然我不是很懂工程这种东西。。。
|
27
magicyu1986 2015-07-30 17:07:28 +08:00
上测试环境一块一块的排查,真没有其他好办法。
最好还是上一套半自动内存管理的东西:智能指针,循环引用检查啥的。 |
28
acgeo 2015-07-30 19:37:33 +08:00
楼上各位说得都是扯犊子的~~
这种情况,吃内存是无法避免的~ 写个shell脚本 定时执行~ 这样每次执行完毕,进程结束会自动释放掉内存.! |
29
matthewgao OP 程序比较老,写的时候没有一个好用的智能指针,然后是一个大牛自己写的智能指针,诡异的就在于各个版本从来没出过问题,就这一台机器,同版本的其他机器也没出过问题,这个机器也没什么特别特殊的配置,所以很诡异
我现在怀疑是STL,有些容器不会自动shrink的问题。 |
30
matthewgao OP 总之还是谢谢各位,我去试试AddressSanitizer,看看有什么效果不
|
31
matthewgao OP 我来做个了结,最终还是靠 review 代码, 找到了泄露的地方, 10w 行。。。
|