我可以重用对象实例来避免使用protobuf-net进行分配吗?

上下文:这是基于在我回答之前被问及然后删除的问题 – 但我认为这是一个很好的问题,所以我整理了它,重新发布并重新发布。

在使用protobuf-net的高吞吐量场景中,大量分配是一个问题(特别是对于GC),是否可以重用对象? 例如,通过添加Clear()方法?

 [ProtoContract] public class MyDTO { [ProtoMember(1)] public int Foo { get; set; } [ProtoMember(2)] public string Bar { get; set; } [ProtoMember(3, DataFormat = DataFormat.Group)] public List Values { get { return values; } } private readonly List values = new List(); public void Clear() { values.Clear(); Foo = 0; Bar = null; } } 

protobuf-net永远不会调用你的Clear()方法本身,但是对于简单的情况,你可以自己简单地做,并使用Merge方法(在v1 API上,或者只是将对象传递给v2 API中的Deserialize )。 例如:

 MyDTO obj = new MyDTO(); for(...) { obj.Clear(); Serializer.Merge(obj, source); } 

这会将数据加载到现有的 obj而不是每次都创建一个新对象。

在更复杂的场景中,您希望减少对象分配的数量, 并且乐于自己处理对象池/重用 ,那么您可以使用自定义工厂。 例如,您可以向MyDTO添加方法,例如:

 // this can also accept serialization-context parameters if // you want to pass your pool in, etc public static MyDTO Create() { // try to get from the pool; only allocate new obj if necessary return SomePool.GetMyDTO() ?? new MyDTO(); } 

并且,在app-startup,配置protobuf-net以了解它:

 RuntimeTypeModel.Default[typeof(MyDTO)].SetFactory("Create"); 

SetFactory也可以接受MethodInfo – 如果工厂方法未在相关类型中声明,则非常有用)

有了这个,应该发生的是使用工厂方法而不是通常的构造机制。 但是,在完成对象清理( Clear() )对象并将它们返回到池中时,完全是你的工作。 工厂方法的特别之处在于它可以用于列表中的新子项等,这些都是Merge无法做到的。