Unity3D游戏GC优化总结---protobuf-net无GC优化实践

protobuf-net优化效果图

  protobuf-net是Unity3D游戏开发中被广泛使用的Google Protocol Buffer库的c#版本,之所以c#版本被广泛使用,是因为c++版本的源代码不支持Unity3D游戏在各个平台上的动态库构建。它是一个网络传输层协议,对应的lua版本有两个可用的库:一个是proto-gen-lua,由tolua作者开发,另外一个是protoc,由云风开发。protobuf-net在GC上有很大的问题,在一个高频率网络通讯的状态同步游戏中使用发现GC过高,所以对它进行了一次比较彻底的GC优化。下面是优化前后的对比图:

 

Unity3D游戏GC优化总结---protobuf-net无GC优化实践

 

protobuf-net优化前GC和性能效果图

 

Unity3D游戏GC优化总结---protobuf-net无GC优化实践

protobuf-net优化后GC和性能效果图

 

 

Unity3D游戏GC优化概述

  有关Unity3D垃圾回收的基本概念和优化策略Unity官网有发布过文章:Optimizing garbage collection in Unity games。这篇文章讲述了Unity3D垃圾回收机制,和一些简单的优化策略,讨论的不是特别深入,但是广度基本上算是够了。我罗列一下这篇文章的一些要点,如果你对其中的一些点不太熟悉,建议仔细阅读下这篇文章:

  1、C#变量分为两种类型:值类型和引用类型,值类型分配在栈区,引用类型分配在堆区,GC关注的是引用类型变量。

  2、GC卡顿原因:堆内存垃圾回收,向系统申请新的堆内存。

  3、GC触发条件:堆内存分配而当内存不足时、按频率自动触发、手动强行触发(一般用在场景切换)

  4、GC负面效果:内存碎片(导致内存变大,GC触发更加频繁)、游戏顿卡

  5、GC优化方向:减速GC次数、降低单次GC运行时间、场景切换时主动GC

  6、GC优化策略:减少对内存分配次数和引用次数、降低堆内存分配和回收频率

  7、善用缓存:对有堆内存分配的函数,缓存其调用结果,不要反复去调用。

  8、清除列表:而不要每次都去new一个新的列表

  9、用对象池:必用

  10、慎用串拼接:缓存、Text组件拆分、使用StringBuild、Debug.Log接口封装(打Conditional标签)

  11、警惕Unity函数调用:GameObject.name、GameObject.tag、FindObjectsOfType<T>()等众多函数都有堆内存分配,实测为准

  12、避免装箱:慎用object形参、多用泛型版本(如List<T>)等,这里的细节问题很多,实测为准

  13、警惕协程:StartCoroutine有GC、yield return带返回值有GC、yield return new xxx有GC(最好自己做一套协程管理)

  14、foreach:unity5.5之前版本有GC,使用for循环或者获取迭代器

  15、减少引用:建立管理类统一管理,使用ID作为访问token

  16、慎用LINQ:这东西最好不好,GC很高

  17、结构体数组:如果结构体中含有引用类型变量,对结构体数组进行拆分,避免GC时遍历所有结构体成员

  18、在游戏空闲(如场景切换时)强制执行GC

 

 

protobuf-net GC分析 protobuf-net序列化

  先分析下序列化GC,deep profile如下:

Unity3D游戏GC优化总结---protobuf-net无GC优化实践

  打开PropertyDecorator.cs脚本,找到Write函数如下:

Unity3D游戏GC优化总结---protobuf-net无GC优化实践

Unity3D游戏GC优化总结---protobuf-net无GC优化实践

1 public override void Write(object value, ProtoWriter dest) 2 { 3 Helpers.DebugAssert(value != null); 4 value = property.GetValue(value, null); 5 if(value != null) Tail.Write(value, dest); 6 }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjfsp.html