Protobuf-net тратит слишком много времени в RuntimeTypeModel.TakeLock

1

Моя проблема очень похожа на проблему в этом вопросе: проблема одновременной производительности protobuf-net в TakeLock. Разница в том, что в нашем случае мы используем данные CompressedSerializer и Deserializing. Следующий код вызывается из 8 разных потоков (по 8-ядерному процессору) каждый раз, когда нам нужно десериализовать данные.

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

Вот результат ANTS Performance Profiler:

Изображение 174551

Первый узел в графе - это наш метод, который вызывает десериализацию с использованием приведенного выше кода. Число слева в каждом поле - это время в секундах, а справа - количество попаданий. Как вы видите, RunTimeTypeModel.TakeLock занимает много времени. В связанном выше вопросе предложение заключалось в прекомпиляции модели. Возможно ли это для CompressedSerializer и метода Deserialize? С точки зрения производительности лучше ли создавать один сериализатор и делиться им среди всех потоков? Это поточно-безопасный?

Теги:
multithreading
protobuf-net

1 ответ

0
Лучший ответ

Попробовав несколько опций и сравнив их производительность с помощью Performance Profiler, я пришел к выводу, что Dictionary<T,K> неправильно поддерживается ProtoBuf-net и даже инициализирует сериализатор заранее, это не поможет.

Решение состоит в том, чтобы завернуть словарь в новый класс как единственный элемент данных. Это не только улучшит производительность в несколько раз, мы увидим улучшение в 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>();
        }
    }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню