googleprotobuf不够灵活?自定义googleprotobuf+unity全方案来了

        研究背景:之所以研究这个呢,看过我上一篇文章的人应该知道,对项目的socket网络部分进行优化,主要优化点之一就是建立对象池,复用byte Array,之前还有个可以优化的部分没有优化,就是因为在用protobuf发送数据对象时,要把Imessage转成byte发送,也就是调用 ToByteArray方法

public static byte[] ToByteArray(this IMessage message)
 {
     ProtoPreconditions.CheckNotNull(message, "message");
     byte[] array = new byte[message.CalculateSize()];
     CodedOutputStream codedOutputStream = new CodedOutputStream(array);
     message.WriteTo(codedOutputStream);
     codedOutputStream.CheckNoSpaceLeft();
     return array;
}

已经标记出来了,每次发送都要调用一次ToByteArray,内部又会分配一个byte数组作为转换的结果并返回,凡是有new的地方是不是就可以想办法用内存池?是的,在这一步看起来没啥问题,我可以仿照这里的写法,自定义一个类似的拓展方法,如下

public static byte[] ToByteArrayOptimiszed(this IMessage message)
 {
     ProtoPreconditions.CheckNotNull(message, "message");
     //byte[] array = new byte[message.CalculateSize()];

     byte[] array = arraypool.rent(message.CalculateSize());
     CodedOutputStream codedOutputStream = new CodedOutputStream(array);
     message.WriteTo(codedOutputStream);
     codedOutputStream.CheckNoSpaceLeft();
     return array;
}

这个arraypool是ArrayPool<byte>.shared对象,.net提供的一个线程安全的内存池,rent方法返回最小大于等于你申请的大小的2的幂次方的内存大小,比如申请10,实际返回16,提供具体看msdn ArrayPool 这下一步所遇到的问题就是CodedOutputStream codedOutputStream = new CodedOutputStream(array);这一行需要修改成指定下标和长度的构造函数,因为不是整个array都是有效数据段,所幸提供了这个构造函数,但是不幸的是,这个构造方法是private的

public CodedOutputStream(byte[] flatArray)
    : this(flatArray, 0, flatArray.Length)
{
}

private CodedOutputStream(byte[] buffer, int offset, int length)
{
    output = null;
    this.buffer = ProtoPreconditions.CheckNotNull(buffer, "buffer");
    state.position = offset;
    state.limit = offset + length;
    WriteBufferHelper.Initialize(this, out state.writeBufferHelper);
    leaveOpen = true;
}

​​​​​​但是但是但是!!!重要的事情说三遍,protobuf是开源的,那么我可以拉下来代码修改然后打包dll,再用到工程中,说干就干,过程中遇到了几个问题,主要参考了以下两篇文章,第一篇是如何打包protobuf成dll。ProtoBuf编译生成Google.Protobuf.dll与Protoc.exe、自定义生成代码规则-CSDN博客

第二篇是发现unity导入dll报错,参考文章Unity导入Goolgle.Protobuf.dll报错_unable to resolve reference 'assembly-csharp'. is -CSDN博客

1.Assembly ‘Library/ScriptAssemblies/Assembly-CSharp.dll’ will not be loaded due to errors:
Reference has errors ‘Google.Protobuf’.
2.Assembly ‘Assets/Plugins/Google.Protobuf.dll’ will not be loaded due to errors:
Unable to resolve reference ‘System.Runtime.CompilerServices.Unsafe’. Is the assembly missing or incompatible with the current platform?
Reference validation can be disabled in the Plugin Inspector.

把打包生成的文件夹里面的其他依赖dll一同导入,问题解决,完美work。

最后,虽然问题是用ArrayPool导致的,但是,用现成的轮子总比重复造轮子要好,而且自己造的轮子也不一定有人家的好,本着学习的目的,可以在github查看arraypool的源码。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值