Быстрая и компактная сериализация объектов в .NET - PullRequest
57 голосов
/ 14 февраля 2009

Я хочу использовать сериализацию объектов для связи по сети между сервером Mono и клиентами Silverlight. Очень важно, чтобы сериализация занимала мало места и была достаточно быстрой, поскольку сервер собирался разместить несколько игр в реальном времени.

Какую технику мне использовать? BinaryFormatter добавляет много служебных данных к сериализованным классам (версия, культура, имя класса, имена свойств и т. Д.), Что не требуется в этом приложении.

Что я могу сделать, чтобы сделать это более эффективным?

Ответы [ 8 ]

68 голосов
/ 14 февраля 2009

Вы можете использовать Буферы протокола . Я изменяю весь свой код сериализации с BinaryFormatter со сжатием на Protocol Buffers и получаю очень хорошие результаты. Он более эффективен как во времени, так и в пространстве.

Существует две реализации .NET: Джон Скит и Марк Гравелл .

Обновление : Официальную реализацию .NET можно найти здесь .

52 голосов
/ 18 августа 2010

У меня есть тесты для ведущих сериализаторов .NET , доступные на основе набора данных Northwind.

Northwind .NET serialization benchmarks

@ marcgravell: двоичный protobuf-net - это самая быстрая тестовая реализация, примерно на 7x быстрее, чем самый быстрый из доступных сериализаторов Microsoft (XML DataContractSerializer) в BCL.

Я также поддерживаю некоторые высокопроизводительные текстовые сериализаторы .NET с открытым исходным кодом:

  • JSV TypeSerializer компактный, чистый, JSON + CSV-подобный формат, который в 3,1 раза быстрее, чем DataContractSerializer
  • , а также JsonSerializer , что в 2,6 раза быстрее.
28 голосов
/ 14 февраля 2009

Как автор, я бы пригласил вас попробовать protobuf-net ; он поставляется с двоичными файлами для Mono 2.0 и Silverlight 2.0, а также быстрый и эффективный . Если у вас возникнут какие-либо проблемы, просто напишите мне по электронной почте (см. Мой профиль переполнения стека); поддержка бесплатная.

Версия Джона (см. Ранее принятый ответ) также очень хороша, но IMO версия protobuf-net более идиоматична для C # - Джон был бы идеальным, если бы вы говорили C # с Java, так что вы могли бы иметь подобный API оба конца.

8 голосов
/ 13 июня 2011

У меня была похожая проблема, хотя я просто использую .NET. Я хотел посылать данные через Интернет как можно быстрее и проще. Я не нашел ничего, что было бы достаточно оптимизировано, поэтому я сделал свой собственный сериализатор с именем NetSerializer .

NetSerializer имеет свои ограничения, но они не повлияли на мой вариант использования. И я некоторое время не проводил тесты, но это было намного быстрее, чем все остальное, что я нашел.

Я не пробовал это на Mono или Silverlight. Могу поспорить, что это работает на Mono, но я не уверен, каков уровень поддержки DynamicMethods в Silverlight.

5 голосов
/ 14 февраля 2009

Вы можете попробовать использовать JSON. Это не так эффективно по пропускной способности, как буферы протокола, но было бы намного проще отслеживать сообщения с помощью таких инструментов, как Wireshark, который очень помогает при устранении проблем. .NET 3.5 поставляется с сериализатором JSON.

4 голосов
/ 14 февраля 2009

Вы можете передать данные через DeflateStream или GZipStream , чтобы сжать их перед передачей. Эти классы живут в пространстве имен System.IO.Compression .

3 голосов
/ 10 августа 2009

У меня была очень похожая проблема - сохранение в файл. Но следующее может также использоваться по сети, так как оно действительно было разработано для удаленного взаимодействия.

Решение состоит в том, чтобы использовать библиотеку Саймона Хьюитта - см. Оптимизация Сериализация в .NET - часть 2 .

Часть 1 статьи гласит (жирным шрифтом является мой акцент): «... Если вы когда-либо использовали удаленное взаимодействие .NET для больших объемов данные, вы обнаружите, что есть проблемы с масштабируемость. Для небольших объемов данных это работает хорошо достаточно, но большие объемы занимают много процессора и памяти, генерирует большие объемы данных для передачи , и может произойти сбой с исключениями Out Of Memory. Существует также большая проблема со временем, необходимым для фактического выполнения сериализация - большие объемы данных могут сделать это невозможным для использования в приложениях .... "

Я получил аналогичный результат для моего конкретного приложения, 40 в разы быстрее экономит и в 20 раз быстрее загружает минут до секунд). Размер сериализованных данных был также сильно снижается. Я точно не помню, но это был хотя бы 2-3 раза.

Начать довольно легко. Однако есть один Гоча: используйте только сериализацию .NET для самых высоких структура данных уровня (для получения сериализации / десериализации начал), а затем вызвать сериализацию / десериализацию работает непосредственно для полей на самом высоком уровне структура данных. Иначе не будет никакого ускорения ... Например, если конкретная структура данных (скажем, Generic.List) библиотека не поддерживается тогда .NET вместо этого будет использоваться сериализация, и это нет-нет. Вместо сериализовать список в коде клиента (или подобном). Для примера см. рядом «Это наша собственная кодировка». в той же функции как указано ниже.

Для справки: код из моего приложения - см. Рядом «Примечание: это единственное место, где мы используем встроенный .NET ...».

2 голосов
/ 22 марта 2013

Вы можете попробовать BOIS, который фокусируется на размере упакованных данных и обеспечивает лучшую упаковку на данный момент. (Я еще не видел лучшей оптимизации.)

https://github.com/salarcode/Bois

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...