记一次C#的GC优化,栈和堆。

    公司游戏项目,为了热更并且减少服务器战斗逻辑计算压力,战斗过程在客户端执行,服务器有一份相同的代码,进行校验。

这时候,战斗代码的性能就显得特别重要,客户端有大量的游戏特效等等需要内存分配。每次GC都会导致客户端表现卡顿。

    使用Unity的性能分析工具Profiler分析得知有一个代码逻辑中频繁创建的对象A,占用了大量的内存,而这个对象A的生命周期又非常短。

   这个时候我就想如果这个对象A在栈上,是不是就能减少堆上的内存分配,减少GC。想分配到栈上就必须是值类型,也就只能改成结构体了。但是这个对象很大,是一个参数类型的对象,里面包含了各种参数字段有20个左右,这种对象如果改成值类型,由于值类型是复制内容副本在栈中的,这样频繁的大内存复制性能开销更大。C#本质论上对这种情况有过说明,

  由于逻辑代码也需要在客户端运行,减少GC是最重要的事情,一次GC导致的战斗表现卡顿几乎让玩家体验荡然无存,各方面考虑之后,我采用了这种方法: struct + ref 形式:

   这个对象改A成结构体,但是字段很多,可能导致频繁复制加大内存开销,为了避免这个结构体作为参数传递给方法时候复制内内容副本加大性能开销,在所有调用结构体的方法上都加上ref关键字,结构体作为引用传递(区别于类型转换,不会导致装箱拆箱),这样既不会导致装箱拆箱又不会导致内容复制,结构体只需要创建一次,占用一次存储。大大降低了内存开销。

  微软官方文档关于ref的介绍https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/keywords/ref#passing-an-argument-by-reference

  实测表明,对于我们项目这个对象A改成结构体后,内存分配直大大降低,跟这个对象相关的代码逻辑内存调用只有之前的1/6。

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值