New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

内存问题 #323

Closed
yibiaochen opened this Issue Aug 11, 2015 · 12 comments

Comments

Projects
None yet
3 participants
@yibiaochen
Contributor

yibiaochen commented Aug 11, 2015

我们一个玩家一个agent,将玩家踢下线关掉agent之后,发现dump_c_mem出来的结果,C层面还有一定的内存没有被销毁,数额不等,大概从200k~1,2M的样子,运行越久未被释放的越多。没有自己写的C服务,全部是lua服务,除了用pbc来跟客户端交互。有人遇到同样的问题么?云风有啥建议查证一下不:-D
ps:跟在ejoy的旧同事交流过,他的测试结果也是有一定残余

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 11, 2015

最好能确认没有销毁的内存到底是什么。

能确定的是:lua 代码本身是不会释放的。但同一份文件只会有一份在内存。

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 11, 2015

我测试了 skynet 目前自带的例子,除了第一次连上去退出后 agent 会遗留内存外,以后再连接的都不会,符合上面我说的结论。

具体你的问题你想查,可以打开 jemalloc 的内存泄露分析,或自己修改 malloc_hook 加入更多信息用来推断没有释放的到底是什么。

@linxiaolong

This comment has been minimized.

linxiaolong commented Aug 11, 2015

我这边情况测了下如下:
2015-08-11 15 11 00
如图 0000001a 00000022 00000024 均为已经杀掉的agent,0000001a是第一个启动的agent,因为有codecache持续留着很正常,后面两个最后都留下64B,也没继续增长

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 11, 2015

肯定是你有 C 代码分配了内存没有释放。建议用如下方法排查:

修改 malloc_hook.c , 在 malloc/free/realloc/calloc 等 skynet 定制版本的函数中加上 log, 把调用信息写到 log 文件中。注意,这里可以拿到是从哪个服务分配出来的,你需要按服务分别 log 到不同文件,方便分析。注:这里可以和 cmemory 采用同样的手法,建一个 64K 静态数组保存 log FILE * ,或直接查入 cmemory 的记录中去。

把最后那个供 lua 使用的分配器中的内存管理调用,绕开上面的函数避免不必要的 log 。因为你要相信 lua vm 一定在内存管理上是绝对干净的。

做此修改后, 你再跑测试, 应该会生成很多 log 文件。 然后写一个脚本分析 log ,看一下有哪些内存块没有释放。由于以上修改排除了 lua vm 的内存操作,所以剩下的应该非常少,或许不用写脚本,人肉就可以得到结论。

一旦发现没有释放的,再进一步推测是哪里的问题。(可以根据长度,或用别的手段)

@yibiaochen

This comment has been minimized.

Contributor

yibiaochen commented Aug 11, 2015

嗯,感谢云风,我先按你的方法看看

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 11, 2015

我想起来,这个方法有点问题。 因为你不能在 malloc hook 里调用文件 api (比如 fopen), 因为它本身会调用 malloc 。就递归了。

所以你需要在进入 malloc hook 时加一个TLS 变量做标记,避免重入。

cloudwu added a commit that referenced this issue Aug 12, 2015

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 12, 2015

我找到问题了, 但是撞鬼了. 今天我这个 bugfix 提交并不是今天修正的. 我的机器上的本地代码里一直有这一行代码. 但是 git 仓库里没有. 并且, 我用 git status 和 git diff 都看不到差异.

这行代码从头到尾都在我的本地机器里. 重新 clone 了一份, 然后才把这行代码修改提交了.

完全不明白 :(

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 12, 2015

所以我自己机器上一直都发现不了问题. 今天在同事机器上找到的.

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 12, 2015

ps. 需要 make cleanall 才会重新编译 lua

@yibiaochen

This comment has been minimized.

Contributor

yibiaochen commented Aug 12, 2015

我合了最新的skynet代码,发现这一行一直是有的(上一次合并是4月份,大概是出了1.0版本出了后不久)。我估计还是我们哪里引起的泄露,我继续查。。

@yibiaochen

This comment has been minimized.

Contributor

yibiaochen commented Aug 13, 2015

@cloudwu

This comment has been minimized.

Owner

cloudwu commented Aug 14, 2015

这个库和 skynet 带的 skynet.pack skynet.unpack 没有差别. 但后来没有维护.

linxiaolong pushed a commit to pigparadise/skynet that referenced this issue Aug 14, 2015

@yibiaochen yibiaochen closed this Aug 15, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment