【问题标题】:Protobuf-net with AoT compiler and object pooling带有 AoT 编译器和对象池的 Protobuf-net
【发布时间】:2018-02-21 18:42:36
【问题描述】:

我一直在调查是否有人找到任何文档或想出如何让对象池与 AoT 编译(iOS 和 WebGL for Unity 需要)一起工作。

我在这里找到了来自 Marc Gravell 的 this answer,它描述了如何让工厂使用您的对象池,但是如果您使用 AoT 预编译器并调用如下代码,这似乎不起作用:

 public static T DeserializeProtoObject<T>(byte[] bytes)
 {
    using (MemoryStream m = new MemoryStream(bytes))
    {
        return (T)m_serializer.DeserializeWithLengthPrefix(m, null, typeof(T),ProtoBuf.PrefixStyle.Fixed32,0);
    }
 }

m_serializer 是使用预编译器创建的,代码如下:

        var model = TypeModel.Create();
        model.Add(typeof(PlayerUpdate), true);
        model.AllowParseableTypes = true;
        model.AutoAddMissingTypes = true;
        model.Compile("IOGameProtoBufSerializer", "IOGameProtoBufSerializer.dll");

看起来模型有一个 SetDefaultFactory() 函数,但我不知道如何使用它。知情人士有什么建议吗?

我的下一步是下载源代码并深入研究。

感谢您的帮助。

编辑: 看起来我在从此处下载完整的 protobuf-net 存储库后找到了示例源:https://github.com/mgravell/protobuf-net

对于那些想要做同样事情的人来说,这里是实际的源代码,展示了如何使用默认构造函数的示例:

using Xunit;
using ProtoBuf;
using ProtoBuf.Meta;
using System;
using System.Threading;
using System.Reflection;
namespace Examples.Issues
{

    public class SO14532116
    {
        [Fact]
        public void Execute()
        {

            var model = TypeModel.Create();
            model.AutoCompile = false;
            model.SetDefaultFactory(typeof(SO14532116).GetMethod("ObjectMaker"));

            int oldCount = Count;
            Test(model, "Runtime");
            model.CompileInPlace();
            Test(model, "CompileInPlace");
            Test(model.Compile(), "CompileInPlace");
            model.Compile("SO14532116", "SO14532116.dll");
            PEVerify.AssertValid("SO14532116.dll");

            int newCount = Count;
            Assert.Equal(oldCount + 3, newCount);
        }

        [ProtoContract]
        public class Foo
        {
            [ProtoMember(1)]
            public int X {get;set;}

            public static Foo Create(int x = 0)
            {
                return new Foo(x);
            }

            public Foo(int x) { X = x; }
        }


        private void Test(TypeModel model, string p)
        {
            var obj = Foo.Create(123);

            int oldCount = Count;
            var clone = (Foo)model.DeepClone(obj);
            int newCount = Count;
            Assert.Equal(oldCount + 1, newCount);
            Assert.Equal(123, clone.X);
        }

        private static int count;
        public static int Count
        {
            get { return Interlocked.CompareExchange(ref count, 0, 0); } 
        }
        public static object ObjectMaker(Type type)
        {
            object obj;
            if(type == typeof(Foo))
            {
                obj = Foo.Create();
            } else {
                obj = Activator.CreateInstance(type);
            }
            Interlocked.Increment(ref count);
            return obj;

        }
    }
}

【问题讨论】:

  • 好的,所以在下载完整的 repo 后,我能够找到 Mark 在另一篇文章中提到的使用默认工厂的示例代码。不幸的是,我不能在这里发表评论。但只需从此处克隆 git 存储库:github.com/mgravell/protobuf-net,然后转到示例 -> 问题 -> SO14532116.cs

标签: protobuf-net


【解决方案1】:

预编译器......笨拙,几乎不可能支持 - 它在 2.3 中几乎不存在,下一个里程碑的关键交付物是用构建时代码生成完全替换它, 2.3 从重写模式工具开始。长期:这应该是一个很多更好的选择!

如何使用SetDefaultFactory的例子可以看here。我不能对预编译器的工作方式抱有任何期望——如果能工作:太好了!

【讨论】:

  • 太好了,谢谢马克。也感谢源链接。旧帖子的链接被破坏了,谷歌没有帮助我。我期待在 2.3 可用时使用新的东西。现在我正在尝试停止为使用 protobuf-net 的多人游戏服务器和相关客户端分配内存。不幸的是,当垃圾收集器运行时,它会导致明显的性能中断。
猜你喜欢
  • 2018-10-27
  • 2022-07-05
  • 2018-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 2011-07-03
相关资源
最近更新 更多