Как protobuf-net достигает достойной производительности? - PullRequest
35 голосов
/ 12 ноября 2009

Я хочу понять, почему решение для буферизации протоколов для .NET , разработанное Марк Грэвелл , так быстро, как оно есть.

Я могу понять, как исходное решение Google достигло своей производительности: оно предварительно генерирует оптимизированный код для сериализации объектов; Я написал несколько сериализаций вручную и знаю, что таким способом можно написать довольно быстрый код, если вы избегаете рефлексии. Но библиотека Марка - это решение во время выполнения, которое использует атрибуты и не создает никакого сгенерированного кода. Итак, как это работает ?

Ответы [ 2 ]

44 голосов
/ 12 ноября 2009

protobuf-net использует шаблон стратегии; при необходимости (только один раз для каждого типа) он использует отражение для просмотра типов и создает набор сериализаторов (на основе общего интерфейса), которые он может использовать для сериализации и десериализации - поэтому при использовании это просто шагает через известный набор сериализаторов.

Внутри что он пытается разумно использовать рефлексию при разговоре с членами; он использует Delegate.CreateDelegate для связи со свойствами и DynamicMethod (и пользовательский IL) для связи с полями (когда это возможно; это зависит от целевой структуры). Это означает, что он всегда говорит с известными типами делегатов, а не с DynamicInvoke (что очень медленно).

Не сходя с ума, код имеет некоторые оптимизации (возможно, за счет читабельности) с точки зрения:

  • локальная byte[] буферизация (потоков ввода / вывода)
  • использование массивов фиксированного размера (а не списков и т. Д.); возможно, слишком много
  • использование дженериков, чтобы избежать бокса
  • многочисленные настройки / твиды / и т.д. вокруг циклов двоичной обработки

Оглядываясь назад, я думаю, что допустил ошибку в отношении дженериков; сложность означала, что принуждение дженериков в систему изогнуло его в нескольких местах и активно вызывает некоторые серьезные проблемы (для сложных моделей) на компактной платформе .

У меня есть несколько проектов (только в моей голове) для рефакторинга этого с использованием не -общих интерфейсов, и вместо этого (для подходящих фреймворков) более широкое использование ILGenerator (мой первый выбор был бы Expression, но это заставляет более высокую версию фреймворка). Проблема, однако, заключается в том, что это займет значительное количество времени, чтобы начать работать, и до самого недавнего времени я был довольно завален .

Недавно мне удалось снова начать тратить некоторое время на protobuf-net , так что, надеюсь, я исправлю свой список невыполненных запросов и т. Д. И скоро начну. Я также намерен заставить его работать с моделями , отличными от , кроме отражения (т. Е. С описанием проводного отображения отдельно).


и не генерирует сгенерированный код

Я также должен уточнить, что есть два (необязательных) маршрута кодега, если вы хотите использовать сгенерированный код; Protogen.exe или надстройка VS позволяют генерировать код из файла .proto. Но это не , необходимое - это полезно, в основном, если у вас есть существующий файл .proto или вы хотите взаимодействовать с другим языком (C ++ и т. Д.) Для разработки на основе контракта.

0 голосов
/ 01 апреля 2014

Его производительность очень хорошая!

Вы можете увидеть полное сравнение между различными форматами, включая protobuf, выполненное http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

Это сравнение включает большие и маленькие выборки данных и различные форматы.

Один из тестов в моем посте enter image description here

...