Быстрая и компактная сериализация объектов в .NET.
Я хочу использовать сериализацию объектов для связи по сети между серверами Mono и Silverlight.
Весьма важно, что сериализация является пространственной эффективностью и довольно быстрой, так как сервер собирается размещать несколько игр в режиме реального времени.
Какую технику я должен использовать? BinaryFormatter добавляет много накладных расходов к сериализованным классам (версия, культура, имя класса, имена свойств и т.д.), Которые не требуются в этом приложении.
Что я могу сделать, чтобы сделать это более экономичным?
Ответы
Ответ 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