cloudwu / skynet

A lightweight online game framework
MIT License
13.33k stars 4.2k forks source link

关于内存使用和lua54 #827

Closed linxiaolong closed 6 years ago

linxiaolong commented 6 years ago

之前在社区提过 #666 #762 两个issue,结合近期压测表现,最终得出原因就是lua53 的GC模式加剧了这种情况,情况大致是:lua53还没来得及GC垃圾内存,新的内存分配需求又陆续有来,结果导致jemalloc切割且冗余的内存在长期来看浪费率极高(假设skynet GC后实际占用内存为m,而GC前包含了垃圾内存可到达2 m,而最终大概经过一天压测,jemalloc抢占内存可以高达2.5 2 * m)。在层层内存优化缓存的体系下,对于游戏服务器这种类型,分代GC或者类似python的引用计数+全量GC模式 会更适合,毕竟内存是有限的,尤其是上云服,各种配置都有定格,除非不计成本,否则内存很难随意增长。

我们目前在内服测试分支已经换上lua54进行测试,从压测结果来看,内存使用很稳定,对比之前lua53不断趋向向上的内存是更让人放心。

想咨询一下cloud: 1)目前lua54的work1版本,按lua社区习惯来说,应该是个非稳定版本?我们暂时只是拿来测试,不过确实测试结果很满意 2)对skynet后续版本会有换上lua54的打算么?

cloudwu commented 6 years ago

lua 5.4 将在正式发布后合并。

对于长期服务,可以用主动调用 gc 的 step 加快循环周期,空闲时更应调用。因为单个 lua vm 的 gc 是由分配驱动的,你不创建新对象,老的就不会回收。对于短期服务,可以尽快退出,利用 close vm 关闭彻底回收。

jemalloc 可以考虑换掉。

cloudwu commented 6 years ago

对于内存紧张的环境,可以考虑不用一个 client 对一个服务;而是多对一。gate 最近做过修改,将 client fd 通过 session 夹带在网络消息中转发,可以用来区分不同的 client 网络消息。

linxiaolong commented 6 years ago

1、jemalloc换掉。这个是指使用其他类似tmalloc之类的? 2、之前试过停掉自动GC,定期调用step,对长期服务在繁忙期会有CPU的影响,这块的使用cloud有什么推荐的方式?

cloudwu commented 6 years ago

可以直接用 glibc 带的,未必会更差。另外,lua vm 注册的 alloc 可以考虑自己写一下。例如,自己 mmap 内存管理。skynet 大部分内存是从 lua vm 里分配的,改写这个可以解决大多数问题。

step 只是对 gc 的一个建议,调用 step 并不需要停掉 gc ,也不需要特别安装定时器调用。我建议在服务收到每条消息时都主动调一下(改写 skynet.dispatch_message 即可)。

linxiaolong commented 6 years ago

1、jemalloc替换的我测试一下 2、改写vm alloc这个事情之前考虑过,因为我们的设计几乎都是长期服务,之前考虑性价比不太高所以没动手,我近期试下 3、每次消息处理调用step,我也测试下,不过比较担心性能会有所下降

sue602 commented 6 years ago

我们也有遇到类似的问题,后来通过两种办法解决。 1.禁用系统默认的jemalloc,使用glibc,make linux MALLOC_STATICLIB= SKYNET_DEFINES=-DNOUSE_JEMALLOC 2.在一些需要修改gc步长。 经过上面两个步骤,发现内存使用比原来的好非常多。

lmess commented 6 years ago

1 jemalloc替换成glibc,这个在高版本linux内核可以试下,我自己测试结果是在2.6.32版本内核下会变差很多。最早尝试过替换成tcmalloc,性能表现跟jemalloc没太大差异,内存表现没测到。 2 GC的一些设置,setpause&setstepmul可以适当加快回收周期,再不济就用step自己控制。不过你的情况重点是内存利用率低。 3 jemalloc可以通过配置来调整内存利用率,lg_dirty_mult&narenas,narenas的设置(减少narenas)效果会比较明显,对性能也有提升。 4 不太建议使用不稳定版本,你压测的时候没问题,不代表线上的复杂情况就稳定。

linxiaolong commented 6 years ago

压测环境:ubuntu14(linux4.4),采用jemalloc5.0 压测方式:一批老号持续不断地进行装备/道具/整理等行为,完全不下线持续至少一天,对比外服正常行为是比较严苛

近期对上次提及的做了些尝试: 1、jemalloc替换。就目前来看,如果完全取消jemalloc,情况变得更糟,无论是初始占用还是后期增长 2、改写vm alloc。采用 https://blog.codingnow.com/2015/07/skynet_lua_allocator.html 所提及的算法,jemalloc关闭和开放的情况都尝试过,从长期内存使用来说情况也较为糟糕 3、每次消息处理调用step。这个比较有效地调动了lua GC的积极性

目前我们采取的方案: 1、jemalloc调整选项:"background_thread:true,dirty_decay_ms:0,muzzy_decay_ms:0",这三个选项的调整对于jemalloc回收合并的积极性有较大提升 2、消息驱动collectgarbage("step"),针对部分内存分配释放频繁的服务采取较大的步长(譬如1024K)

目前效果比较良好,经过大概两天时间持续压测,内存使用会稳定在一个范围,持续增长的趋势有效控制抑或说大大减缓

上面有其他朋友说的其他方式而呈现不同的结果,估计跟环境和测试方式有些关系,不做深究。希望后面的朋友遇到此类问题,在lua54还没release/skynet还未合并lua54之前,也可以有个解决的手段,或者一起分享。