Protobuf-net在RuntimeTypeModel.TakeLock中花费了过多的时间

时间:2014-05-27 21:54:49

标签: c# multithreading protobuf-net

我的问题与此问题中的问题非常相似:protobuf-net concurrent performance issue in TakeLock。不同的是,在我们的例子中,我们使用CompressedSerializer和反序列化数据。每次我们需要反序列化数据时,都会从8个不同的线程(在8核CPU上)调用以下代码。

var result = new ProtoCompressedSerializer().Deserialize<Dictionary<string, CustomStruct>>(...)

以下是ANTS Performance Profiler的结果:

ANTS Performance Graph

图中的第一个节点是我们使用上面的代码调用反序列化的方法。每个框中左侧的数字是以秒为单位的时间,右侧是命中计数。正如您所看到的,RunTimeTypeModel.TakeLock花费了大量时间。在上面的链接问题中,建议是预编译模型。这可能是CompressedSerializer及其反序列化方法吗?从性能角度来看,创建一个序列化程序并在所有线程中共享它更好吗?它是线程安全的吗?

1 个答案:

答案 0 :(得分:0)

在尝试了几个选项并使用Performance Profilers比较它们的性能之后,我得出的结论是Dictionary<T,K>未被ProtoBuf-net正确支持,甚至预先初始化序列化器也不会有帮助

解决方案是将Dictionary包装成一个新类作为唯一的数据成员。这不仅可以提高性能几倍,我们看到了3倍的改进,而且几乎消除了TakeLock的使用和相关的超时问题。

示例:

    [Serializable]
    [ProtoContract]
    [DataContract]
    public class ModelADict
    {
        [ProtoMember(1)]
        [DataMember]
        public Dictionary<string, ModelA> sub { get; set; }

        public ModelADict()
        {
            sub = new Dictionary<string, ModelA>();
        }
    }