我可以再利用的对象实例,以避免与分配protobuf网? [英] Can I re-use object instances to avoid allocations with protobuf-net?

查看:316
本文介绍了我可以再利用的对象实例,以避免与分配protobuf网?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:这是基于有人问,然后被删除之前,我能回答的问题 - 但我认为这是一个很好的问题,所以我收拾它,改写它,并重新贴吧

在高通量方案使用protobuf网,其中许多分配是个问题(特别是用于GC),是有可能再利用对象?例如通过增加一个清除()的方法?

  [ProtoContract]
公共类MyDTO
{
    [ProtoMember(1)]
    公众诠释富{获得;组; }
    [ProtoMember(2)]
    公共字符串吧{获得;组; }
    [ProtoMember(3,DATAFORMAT = DataFormat.Group)
    公开名单< INT>值{获得{返回值; }}
    私人只读表< INT>值=新的名单,其中,INT>();

    公共无效清除()
    {
        values​​.Clear();
        富= 0;
        酒吧= NULL;
    }
}
 

解决方案

protobuf网绝不会叫你的清除()方法本身,但对于简单的情况下,你可以简单地做自己,并使用合并方法(在V1 API,或者只是对象传递到反序列化的V2 API)。例如:

  MyDTO OBJ =新MyDTO();
对于(...) {
    obj.Clear();
    Serializer.Merge(OBJ,源);
}
 

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

在要减少对象分配的数量,的,并高兴地处理对象池/再利用自己的的,那么你可以使用自定义的工厂更复杂的情况。例如,您可以添加一个方法来 MyDTO 如:

  //这也可以接受序列化背景下的参数,如果
//你想通过你的游泳池中,等
公共静态MyDTO创建()
{
    //尝试从池中获取;如有必要,只分配新的OBJ
    返回SomePool.GetMyDTO()?新MyDTO();
}
 

和,在应用程序,启动,配置protobuf网了解一下吧:

  RuntimeTypeModel.Default [typeof运算(MyDTO)SetFactory(创建)。
 

SetFactory 也可以接受的MethodInfo - 有用的,如果工厂方法不是里面有问题的类型声明)

通过这个,会发生什么是工厂方法是使用的而不是的通常的建设机制。然而,仍存在,完全是你的工作就是清洗(清除())当你完成了他们,并给他们返回到您的池的对象。什么是特别好的关于工厂的做法是,它会为新的分项列表等,你不能仅仅从执行合并

Context: this is based on a question that was asked and then deleted before I could answer it - but I think it is a good question, so I've tidied it, rephrased it, and re-posted it.

In a high-throughput scenario using protobuf-net, where lots of allocations are a problem (in particular for GC), is it possible to re-use objects? For example by adding a Clear() method?

[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<int> Values { get { return values; } }
    private readonly List<int> values = new List<int>();

    public void Clear()
    {
        values.Clear();
        Foo = 0;
        Bar = null;
    }
}

解决方案

protobuf-net will never call your Clear() method itself, but for simple cases you can simply do this yourself, and use the Merge method (on the v1 API, or just pass the object into Deserialize in the v2 API). For example:

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

This loads the data into the existing obj rather than creating a new object each time.

In more complex scenarios where you want to reduce the number of object allocations, and are happy to handle the object pooling / re-use yourself, then you can use a custom factory. For example, you can add a method to MyDTO such as:

// 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();
}

and, at app-startup, configure protobuf-net to know about it:

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

(SetFactory can also accept a MethodInfo - useful if the factory method is not declared inside the type in question)

With this, what should happen is the factory method is used instead of the usual construction mechanisms. It remains, however, entirely your job to cleanse (Clear()) the objects when you are finished with them, and to return them to your pool. What is particularly nice about the factory approach is that it will work for new sub-items in lists, etc, which you can't do just from Merge.

这篇关于我可以再利用的对象实例,以避免与分配protobuf网?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆