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

Быстрая и компактная сериализация объектов в .NET.

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

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

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

4b9b3361

Ответ 1

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

Существуют две реализации .NET: Jon Skeet и Марк Гравелл.

Ответ 2

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

Northwind .NET serialization benchmarks

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

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

  • JSV TypeSerializer - компактный, чистый JSON + CSV-подобный формат, который в 3,1 раза быстрее, чем DataContractSerializer
  • а также JsonSerializer, который быстрее 2.6x.

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

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

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

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

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

Ответ 8

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

https://github.com/salarcode/Bois