Replies: 7 comments 5 replies
-
|
profile 的区别仅在于调用的获取系统时间 api 不同,尤其是在监测的函数中没有让出时,它等价于调用两次获取时间的逻辑。 profile 获取时间的实现在 https://github.com/cloudwu/skynet/blob/master/service-src/service_snlua.c#L99-L121 ,你可以尝试修改成和 hpc 实现一致。 ps. 上面主贴的排版没编辑好,建议重新用 markdown 编辑一下。 |
Beta Was this translation helpful? Give feedback.
-
|
相关源码我之前已经找到并简单排查过,没发现什么特别的问题。我咨询ai反馈说是否存在gc导致这种问题。 |
Beta Was this translation helpful? Give feedback.
-
|
我这边先换成hpc机制测试看下效果。 |
Beta Was this translation helpful? Give feedback.
-
排查步骤(按云大思路)结论问题基本确定了,就是gc的问题,所有调用时间大于1毫秒的调用前后,内存都是缩小的,而小于1毫秒的正常执行,内存都是有较小增长的,以下是相关日志(只记录了慢的): 根本原理:当你使用 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ti) 来测量一段 Lua 函数调用(或一段包含多个函数调用的业务逻辑)的耗时时,测量到的 CPU 时间不仅包含业务逻辑本身消耗的 CPU 时间,还包含了在这段代码执行期间,穿插在其中的所有 GC 步骤所消耗的 CPU 时间。 下一步研究方向:如何避免lua的gc对业务层逻辑的影响,比如战斗卡顿、定时器错过执行周期等 感谢云大提供建议方案。 |
Beta Was this translation helpful? Give feedback.
-
|
建议关闭GC 后续定期慢慢释放
fastfullstack.com ***@***.***> 于2025年6月26日周四 17:07写道:
… 排查步骤(按云大思路)
1. 先用纯hpc代替profile(完全去掉)
- 结果与之前基本一至,可以说明与profile的实现机制完全无关,也即并非profile自身占用了时间或其计算时间不对
2. 考虑gc影响
- 增加监控前后的内存变化量来观察gc的执行情况
结论
问题基本确定了,就是gc的问题,所有调用时间大于1毫秒的调用前后,内存都是缩小的,而小于1毫秒的正常执行,内存都是有较小增长的,以下是相关日志(只记录了慢的):
[once][0][0][2025-06-26 16:13:21.64][0x73d51b825a68][ghttp_debug1][0][nnprofile][297][stop_:close->_after_fun->stop->stop_(297)]fun:gperiod_task.time_fun, cur_call_stack._start_hpc:280800000613376, stop_hpc:280800001790392, stop_hpc - cur_call_stack._start_hpc:0.001177016, cur_call_stack._start_collectgarbage_count:1008.3466796875, collectgarbage('count'):498.1611328125, cur_call_stack_total_elapsed_time:0.001175402
[once][0][0][2025-06-26 16:15:26.84][0x73d51e44f048][ggateserver1][0][nnprofile][297][stop_:reset_new_task_time->close->_after_fun->stop->stop_(297)]fun:gperiod_task.time_fun, cur_call_stack._start_hpc:280925201920823, stop_hpc:280925203120202, stop_hpc - cur_call_stack._start_hpc:0.001199379, cur_call_stack._start_collectgarbage_count:2373.912109375, collectgarbage('count'):1973.2685546875, cur_call_stack_total_elapsed_time:0.001198327
[once][0][0][2025-06-26 16:20:26.84][0x73d51e44f048][ggateserver1][0][nnprofile][297][stop_:reset_new_task_time->close->_after_fun->stop->stop_(297)]fun:gperiod_task.time_fun, cur_call_stack._start_hpc:281225201118400, stop_hpc:281225203404178, stop_hpc - cur_call_stack._start_hpc:0.002285778, cur_call_stack._start_collectgarbage_count:2600.5556640625, collectgarbage('count'):1540.34765625, cur_call_stack_total_elapsed_time:0.002284816
根本原理:
当你使用 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ti) 来测量一段 Lua
函数调用(或一段包含多个函数调用的业务逻辑)的耗时时,测量到的 CPU 时间不仅包含业务逻辑本身消耗的 CPU
时间,还包含了在这段代码执行期间,穿插在其中的所有 GC 步骤所消耗的 CPU 时间。
下一步研究方向:
如何避免lua的gc对业务层逻辑的影响,比如战斗卡顿、定时器错过执行周期等
感谢云大提供建议方案。
—
Reply to this email directly, view it on GitHub
<#2063 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAK6QJUL5RPA5V2EUDYTA6L3FOZ5BAVCNFSM6AAAAACACQKDVCVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTGNJYGMZDEMA>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
|
经研究(ai支持和测试验证)发现,gc可能在内存分配、函数调用边界、循环迭代等位置插入执行点,即使通过各种内存优化,包括对象池等的预分配策略优化后,也远无法达到性能监测的准确性,终级策略只能采用在监控前后临时关闭和打开gc的方案,但这样风险较大,所以我目前的策略是只在非生产环境使用此方案以统计系统性能参数,而线上环境则不使用gc方案。 |
Beta Was this translation helpful? Give feedback.
-
|
目前好像没有找到完全完美的解决方案,因为即使关闭gc,在特定的时候,lua仍然会自己执行gc,所以我目前的终级方案是在监控前后统计一个内存值,通过这个差值对比执行时间来评估中间是否包含了gc操作。如果要减少统计偏差值,可以在监控前关闭gc,然后统计后再打开。 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
我在使用
profile.start/profile.stop进行函数调用性能监控时,发现一个异常现象:一个本应简单的函数gperiod_task.time_fun偶尔会出现耗时超过 100 毫秒的情况。该函数核心逻辑仅为调用skynet.time()。关键排查点
skynet.hpc辅助验证核心疑问
如果耗时是监控机制(包括元表和
<close>机制)本身的开销:异常日志记录
(仅当耗时 >1 毫秒时输出日志)
0.110147945=skynet.hpc统计值(已从纳秒转换为秒)0.110134711= profile 统计值相关代码
Beta Was this translation helpful? Give feedback.
All reactions