Подтвердить что ты не робот

Как protobuf-net достигает респектабельной производительности?

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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


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

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

Ответ 2

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

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

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

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