y3-editor / y3-lualib

MIT License
134 stars 40 forks source link

莫名的大内存申请 #472

Closed xiaoqiangCai closed 1 month ago

xiaoqiangCai commented 2 months ago

哈喽,需要帮助。

监控发现哪怕是空项目,时不时会有2M甚至4M的内存被申请导致一个巨大的帧波动,除了这个之外,时不时(没找到规律)还有100K左右的内存申请导致哪怕一个空函数也会耗时巨大比如0.8ms

这是为什么,可能得原因是啥,我们能做什么呢?

PS. 为了拿到这些数据启用了network模块

xiaoqiangCai commented 2 months ago

内存申请与耗时之间的关系,从打点时间上吻合

xiaoqiangCai commented 2 months ago

大内存必然是2M或者4M这样的关系,小内存(上文100K)则不固定,可能80\90,可能150这样

sumneko commented 2 months ago

你说的内存指的是Lua使用 collectgarbage 'count' 获取的内存,还是整个进程占用的内存?

sumneko commented 2 months ago

QQ_1721013921366 我使用自己的测试项目,Lua虚拟机的内存占用始终没有超过7M

xiaoqiangCai commented 2 months ago

你说的内存指的是Lua使用 collectgarbage 'count' 获取的内存,还是整个进程占用的内存?

是的,统计值都是通过这个拿到的

xiaoqiangCai commented 2 months ago

QQ_1721013921366 我使用自己的测试项目,Lua虚拟机的内存占用始终没有超过7M

我的测试项目不太好发给你,你的这个能发给我不,我跑一下看看呢

sumneko commented 2 months ago

Y3库开发3.zip

xiaoqiangCai commented 2 months ago

我把监控移入之后,纯粹只监控内存变化,跑了一段时间,刚开始是挺正常的,还是发现了大内存的申请,小内存不断。这个过程中,我把clock的移除了,纯粹只有count和network

image

sumneko commented 2 months ago

这些坐标的单位是啥

xiaoqiangCai commented 2 months ago

这些坐标的单位是啥

左边是MB,右边是KB,就是表明他自己在前后两帧申请了大内存

sumneko commented 2 months ago

你的代码太复杂了,而且还引入了自己的dll,很难判断

xiaoqiangCai commented 2 months ago

你的代码太复杂了,而且还引入了自己的dll,很难判断

额,我给你的script里面,只用到了dll的clock内容。另外,整个逻辑就是在mentest里面每帧统计了一个count内存,然后上传,没了

xiaoqiangCai commented 2 months ago

你的代码太复杂了,而且还引入了自己的dll,很难判断

额,我给你的script里面,只用到了dll的clock内容。另外,整个逻辑就是在mentest里面每帧统计了一个count内存,然后上传,没了

甚至,案发现场,我是把clock的代码都注释掉了

sumneko commented 2 months ago

获取时间可以用 os.clock_bannedpython.debug_ns_timestamp 结果可以先打印到日志里,然后解析一下日志

毕竟我这里空跑只有6M内存,而你的截图里都上90M了,很难不怀疑是你引入的dll有啥问题

xiaoqiangCai commented 2 months ago

获取时间可以用 os.clock_bannedpython.debug_ns_timestamp 结果可以先打印到日志里,然后解析一下日志

毕竟我这里空跑只有6M内存,而你的截图里都上90M了,很难不怀疑是你引入的dll有啥问题

启动的时候也是跟你一样的,个位数的内存,截图这是是给他跑了两小时之后的,我会看大内存警告找出来的

xiaoqiangCai commented 2 months ago

我把dll去掉吧,理论上说,我就是怕这个会对你判断有影响,案发的时候特地把y3.gclock相关的在memtest里面的代码注释掉才跑的。

我完全移除dll,再跑一轮看看

xiaoqiangCai commented 2 months ago

image

在4000帧的时候,就出现了一个67的小内存,这次是完全没有dll的

sumneko commented 2 months ago

理论上空跑无论跑多久内存都内存都不应该变化的,90+M应该有内存泄露了

sumneko commented 2 months ago

啥叫67的小内存

xiaoqiangCai commented 2 months ago

image

就是比较前后两帧的内存变化,值太大了,我就输出来一个警告

xiaoqiangCai commented 2 months ago

这里单位是KB,跟我之前提到的小内存(100KB左右复合)

xiaoqiangCai commented 2 months ago

image

这个经历几轮GC之后,内存的基点确实是在不停上涨,我不太懂为啥,是因为对象进入老年代,没有触发full gc的原因?

sumneko commented 2 months ago

做个按键事件手动调用一下 collectgarbage() 看看,如果能变回初始内存大小就不用管

xiaoqiangCai commented 2 months ago

降不下去,手动的,基点也是在缓慢增长

sumneko commented 2 months ago

QQ_1721027371937 我这边快进到13个小时依然只有6M内存占用,应该是你代码里有内存泄露

sumneko commented 2 months ago

你用 .ss 打印一下内存快照看看,然后用 .ct 查询一下可疑对象的应用

xiaoqiangCai commented 2 months ago

QQ_1721027371937 我这边快进到13个小时依然只有6M内存占用,应该是你代码里有内存泄露

  1. 咋快进的...还有这功能?
  2. 我看代码是比较不出来了,我试试你说的这个内存快照的方法
xiaoqiangCai commented 2 months ago

我好像找到了,我改一下试一下看看。这个snapshot工具很6

xiaoqiangCai commented 2 months ago

你用 .ss 打印一下内存快照看看,然后用 .ct 查询一下可疑对象的应用

基点涨的是修复了,但是上面的提到的小内存问题,还是会有

sumneko commented 2 months ago

内存持续增长很正常,计时器底层和network都会不停的制造内存。一帧增长100k有可能是你序列化、反序列化了一个比较大的数据结构。

xiaoqiangCai commented 2 months ago

内存持续增长很正常,计时器底层和network都会不停的制造内存。一帧增长100k有可能是你序列化、反序列化了一个比较大的数据结构。

不是这个意思,我抓一个给你看一下,他的增长时间点很多时候对应的是空函数的返回,就很奇怪

xiaoqiangCai commented 2 months ago

好像抓不到了我认为有问题的小内存申请,目前出现的都基本是你说的那种情况,大部分应该是buff字符串拼接和序列化的消耗

xiaoqiangCai commented 2 months ago

还是会有这种情况的内存块申请,不知道为啥

image

image

delta=after-before, 问题是这段之间基本没逻辑,却显示开销了129KB...

sumneko commented 2 months ago

有没有触发 log.error

xiaoqiangCai commented 2 months ago

有没有触发 log.error

没有,前后日志在这了

image

sumneko commented 2 months ago

我之前看你代码好像网络会不定时回包?是不是刚好回了个包过来解析了一下

xiaoqiangCai commented 2 months ago

我之前看你代码好像网络会不定时回包?是不是刚好回了个包过来解析了一下

即使会这样,但是也说不通,因为在这个日志逻辑帧循序执行的吧,难到还会并行插入数据,或者说网络包底层会并行往lua写入数据吗

sumneko commented 2 months ago

简单看了下你的atex里面有几个数组会不停的扩展,他们预期会有多长?

xiaoqiangCai commented 2 months ago

简单看了下你的atex里面有几个数组会不停的扩展,他们预期会有多长?

一个trace日志的行数,在这里固定9或者10行

xiaoqiangCai commented 2 months ago

简单看了下你的atex里面有几个数组会不停的扩展,他们预期会有多长?

一个trace日志的行数,在这里固定9或者10行

image

sumneko commented 2 months ago

之前测试的时候是关掉调试器的吗,我看你发我的代码里是注掉调试器的

xiaoqiangCai commented 2 months ago

之前测试的时候是关掉调试器的吗,我看你发我的代码里是注掉调试器的

没,我把那个调试器的代码挪到了main下了

上面事发的是开着调试器的

sumneko commented 2 months ago

关一下调试器试试看,调试器即使你不连接也会有一定开销的(会hook函数调用)

xiaoqiangCai commented 2 months ago

关一下调试器试试看,调试器即使你不连接也会有一定开销的(会hook函数调用)

我试一下,还得观察一下数据

xiaoqiangCai commented 2 months ago

关一下调试器试试看,调试器即使你不连接也会有一定开销的(会hook函数调用)

image

出现了

xuhuanzy commented 1 month ago

你的代码太复杂了,而且还引入了自己的dll,很难判断

不是在平台下不能用dll吗

xiaoqiangCai commented 1 month ago

你的代码太复杂了,而且还引入了自己的dll,很难判断

不是在平台下不能用dll吗

本地环境下的

xuhuanzy commented 1 month ago

内存诊断工具用的啥

xiaoqiangCai commented 1 month ago

@sumneko 这个地方是问题吗

function json.encode(v)
    statusVisited = {}
    statusBuilder = {}
    encode(v)
    return table_concat(statusBuilder)
end

statusBuilder 需要在下一次调用encode时候才会释放,这样会不会导致对象容易晋升到老年代

xiaoqiangCai commented 1 month ago

内存诊断工具用的啥

自个写...