跳转至

IGG开发笔记

待分析

PureMVC

说明:https://blog.csdn.net/wangjiangrong/article/details/107686954
官方文档:http://puremvc.org/docs/PureMVC_IIBP_Chinese.pdf
github c#: https://github.com/PureMVC/puremvc-csharp-standard-framework
github: https://github.com/PureMVC
官网:http://puremvc.org (提供pdf中文文档)

如果在 Mediator 里有很多对 View Component 的操作(响应 Event 或Notification),那么应该考虑将这些操作封装为 View Component 的一个方法,提高可重用性。 如果一个 Mediator 有太多的对 Proxy 及其数据的操作,那么,应该把这些代码重构在 Command 内,简化 Mediator,把业务逻辑(Business Logic)移放到Command 上,这样 Command 可以被 View 的其他部分重用,还会实现 View 和Model 之间的松耦合提高扩展性

网络通信优化

游戏内通信协议使用Sproto序列化

通信反序列化分析

优化前:
当前截图为win10 unity editor测试
编号为1的测试数据,每帧解析30001协议50次的开销,测试数据为Map_ObjectInfo.request,数据包含有60个MapObjectInfo对象

协议开销分析 1. SocketAsyncEventArgs mReceiveEventArgs 异步socket 收到网络数据 1. 网络数据 写入mReceiveBuffer中 > 1. 然后CopymReadQueueBuffer(网络数据拆包)进行传递 > 1. 然后使用packetData进行派发,packetData是新的buffer >
>
> 1. 通过Socket异步回调线程将packetData 存储到private LockFreeQueue<MemoryStream> mReceivePacketQueue队列中,然后通过unity主线程进行派发,在主线程中进行Decode > 1. Decode时,MemoryStream.ToArray()进行拷贝,生成新的buffer >
>
>
>
>
1. Decode首先进行解压缩,解压缩时先把原始bufferCopynewBuffernewBuffer是新的buffer > 1. 然后进行解压缩decomBuffer,解压缩decomBuffer是新的buffer > > 1. 解压后进行解密outBuffer,解密是新的buffer > 1. 解密后进行解包unpack_data,解包是新的buffer > 1. 解包后解析对象Package 1. 解析对象后进行解析对象GateMessage,GateMessage对象有新的byte[]字段,该字段有新的buffer > 收到的每个协议先反序列化成GateMessage对象,该对象的字段private List<MessageContent> _content; 带有private byte[] _networkMessage;字段,这个字段是真实协议对象的原始数据,gc严重 > > 1. 将解析对象封装到RpcInfo对象中 1. 使用GateMessage进行解包unpack_data,解包是新的buffer 1. 开始解析具体业务对象,同时会封装到RpcInfo中 1. RpcInfo进行解封,使用具体业务对象进行业务派发

通信反序列化优化

  1. 调整Sproto反序列化流程,使其支持缓存重复利用,将MessageContentbyte[]调整为BufferStream,支持重复利用buffer,减少GC
  2. packetDataMemoryStream 替换成RecyclableMemoryStream,进行缓存利用,且支持跨线程处理
  3. 调整业务,替换掉MemoryStream.ToArray(),解析过程使用RecyclableMemoryStream

  4. 解压缩前使用的decomBuffer,替换为常驻的大buffer,只创建一次,就不销毁了,重复利用

  5. 解压缩后使用的decomBuffer,替换为常驻的大buffer,只创建一次,就不销毁了,重复利用
  6. 解密后使用的outBuffer,替换为常驻的大buffer,只创建一次,就不销毁了,重复利用
  7. 解包使用的unpack_data,这里使用两个大buffer进行处理,只创建一次,就不销毁了,重复利用, > 解析协议GateMessage前执行unpack,解析协议GateMessage后,解析具体业务协议前也会执行unpack,这里剥离具体业务的影响,进行分步处理,使用两个大buffer分别对应两次解析协议
  8. RpcInfoGateMessage.requestGateMessage.responseMessageContent等等对象需要进缓存池,这些对象是为反序列化服务的
  9. 调用频繁的业务协议使用缓存池进行处理 >MessageContent是工具生成的,为了防止冲突,改为MessageContentEx
    >

优化中期参照:
编号为1的测试数据,每帧解析30001协议50次的开销,测试数据为Map_ObjectInfo.request,数据包含有60个MapObjectInfo对象

上面结果是将所有协议都做缓存,包括MapObjectInfo内部字段引用的协议
上面是将MapObjectInfoEntityDictionary使用MapObjectInfo,不创建新的,具体业务会有bug et.heros = new System.Collections.Generic.Dictionary<System.Int64,SprotoType.BattleHeroInfo>();

优化最终结果: 编号为1的测试数据,每帧解析30001协议50次的开销,测试数据为Map_ObjectInfo.request,数据包含有60个MapObjectInfo对象

MapObjectInfo的内部字段引用的协议类型没有做缓存(多个协议会引用相同的协议,复杂度太高);
MapObjectInfoEntityDictionary还是创建新的,否则业务有bug;

测试数据优化前后GC对比 编号为1的测试数据,每帧解析30001协议50次的开销,测试数据为Map_ObjectInfo.request,数据包含有60个MapObjectInfo对象
优化前 15.9MB 优化后 4.8MB


游戏中优化前后对比:
优化前每一次调用 GC255kb 优化后第一次调用 GC114.1kb 优化后第二次调用 GC86.6kb

对进入地图场景初始化的Map_ObjectInfo.request协议数据50倍测试 优化前 15.9MB 优化后 4.8MB

PoolMgr的缓存池测试