2009-03-31 4 views
11

Каковы недостатки встроенного BinaryFormatter. Чистая сериализация? (Производительность, гибкость, ограничения)Каковы недостатки встроенной сериализации на основе BinaryFormatter .Net?

При необходимости, пожалуйста, сопровождайте свой ответ.

Пример:

Пользовательские объекты сериализации должны быть украшены [Serializable] атрибут или реализовать интерфейс ISerializable.

Менее очевидный пример:

Анонимные типы не могут быть упорядочены.

ответ

16

Если вы имеете в виду BinaryFormatter:

  • базируясь на полях, очень нетерпимой версия; изменить личные детали реализации, и он рвется (даже просто changing it to an automatically implemented property)
  • не является кросс-совместимым с другими платформами
  • не очень дружелюбны к новым полям
  • является сборка (метаданные сжигается в)
  • является MS/.NET конкретные (и, возможно, .NET от версии)
  • не запутывания безопасной
  • не особенно быстро, или небольшой выход
  • не работает на легких структур (CF?/Silverlight)
  • имеет угнетающее привычку вытягивать в вещах, которые вы не ожидали (как правило, через event сек)

Я провел много времени в этой области, в том числе написания (бесплатно) реализации «протокол от Google буферов "для API сериализации; protobuf-net

Это:

  • smaller output and faster
  • кросс-совместимый с other implementations
  • расширяемый
  • контракт на основе
  • obfuscation safe
  • сборки независимая
  • это открытый стандарт документированные
  • работает на всех версиях .NET (Предостережение: не протестированных Micro Framework)
  • имеет крючки для подключения к ISerializable (для ремоутинга и т.д.) и WCF
+0

yerp Я имел в виду сериализацию на основе BinaryFormatter ... расширил вопрос, чтобы указать –

2

Для любого случайного объекта, it's very difficult to prove whether it really is serializable.

+1

Неустранимая проблема с сериализацией заключается в том, что если объект 'Foo' содержит ссылку на объект, на который также ссылается' Bar', а 'Foo' не имеет возможности запросить« Bar »об этой ссылке, то наличие Ссылка «Бар» может стать существенным аспектом состояния «Foo», но сериализатор не сможет это знать. – supercat

1

Если вы меняете объект, который вы сериализуете, все старые данные, которые вы сериализовали и сохранили, сломаны. Если вы храните в базе данных или даже в формате XML, проще преобразовать старые данные в новые.

+1

Не совсем верно изменение должно быть разбито ... http://msdn.microsoft.com/en-us/library/system.runtime.serialization.optionalfieldattribute.aspx –

2

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

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

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

1

Не гарантируется, что вы можете сериализовать объекты взад и вперед между различными Framework (Say 1.0, 1.1, 3.5) или даже с другими CLR Реализации (Моно), опять же, XML лучше для этой цели.

+0

Или другой двоичный формат; см. мой ответ ... –

1

Другой вопрос, что пришло на ум:

XmlSerializer классы расположены в совершенно другом месте от родовых форматтеров времени выполнения. И хотя они очень похожи на использование, XmlSerializer не реализует интерфейс IFormatter. У вас не может быть кода, который позволяет просто поменять форматтера сериализации на или во время выполнения между BinaryFormatter, XmlSerializer или настраиваемым форматированием, не перепрыгивая через некоторые дополнительные обручи.

+0

XmlSerializer предназначен для совершенно иной цели, чем сериализатор времени исполнения и форматирование. Вы не захотите поменяться местами. –

1

Типы сериализуемый должны быть украшены [Serializable] атрибута.

Если вы имеете в виду переменные в классе, вы ошибаетесь. Публичные переменные/свойства автоматически сериализуются.

+0

Я действительно подозреваю, что он имел в виду сам класс, но это все еще неправильно, потому что у вас также есть возможность реализовать ISerializable. Даже если это правильно, я не думаю, что это совсем плохо. –

+0

Извините, я имею в виду, что сам класс расширит этот пример –

+0

Это зависит от API; BinaryFormatter/SoapFormatter работают против полей (открытых или закрытых); XmlSerializer работает против открытых элементов (полей или свойств); DataContractSerializer работает (в идеале) с элементами, помеченными [DataMember]. –

0

Немного менее очевидно, что производительность довольно скудна для сериализации объектов.

Example

Время для сериализации и десериализации 100000 объектов на моей машине:

Time Elapsed 3 ms 
Full Serialization Cycle: BinaryFormatter Int[100000] 

Time Elapsed 1246 ms 
Full Serialization Cycle: BinaryFormatter NumberObject[100000] 

Time Elapsed 54 ms 
Full Serialization Cycle: Manual NumberObject[100000] 

В этом простом примере сериализации объекта с одним полем Int занимает 20x медленнее, чем делать это вручную. Конечно, в сериализованном потоке есть информация о типе. Но это вряд ли объясняет 20-кратное замедление.

0

Я согласен с последний ответ. Производительность довольно плохая. Недавно моя команда кодировщиков закончила преобразование моделирования со стандартного C++ в C++/CLI. В C++ у нас был механизм ручной работы, который работал достаточно хорошо. Мы решили использовать механизм сериализации, а не переписывать старый механизм устойчивости.
Старое симуляция с размером памяти от 1/2 до 1 Gig и большинством объектов, имеющих указатели на другие объекты и 1000 объектов во время выполнения, будет сохраняться в двоичном файле размером от 10 до 15 мегабайт в минуту. Восстановление из файла было сопоставимым.
Использование одних и тех же файлов данных (работающих бок о бок), текущая производительность C++/CLI примерно вдвое превышает C++, пока мы не сделаем упорство (сериализация в новой версии) Writng занимает от 3 до 5 минут , чтение занимает от 10 до 20. Размер файла сериализованных файлов примерно в 5 раз больше, чем у старых файлов. В основном мы видим 19-кратное увеличение времени чтения и 5-кратное увеличение времени записи. Это неприемлемо, и мы ищем способы исправить это.

При изучении двоичных файлов я обнаружил несколько вещей: 1. Данные типа и сборки записываются в ясный текст для всех типов. Это пространственно неэффективно. 2. Каждый объект/экземпляр каждого типа имеет разборную информацию о типе/сборке. Одна вещь, которую мы делали в нашей руке, помогала мечансиму, выписывала известную таблицу типов. Когда мы открывали типы в письменном виде, мы искали его существование в этой таблице. Если он не существует, запись была создана с информацией типа и назначенным индексом. Затем мы передали тип infor как целое число. (тип, данные, тип, данные) Этот «трюк» значительно сократит размер. Для этого может потребоваться дважды выполнить данные, однако процесс «на лету» можно было бы развить, в дополнение к добавлению его к таблице, нажав на поток, если бы мы могли гарантировать порядок ресортации из потока ,

Я надеялся повторно реализовать некоторые из основных сериализации, чтобы оптимизировать его таким образом, но, увы, классы запечатаны! Мы все еще можем найти способ забросить его.

0

Другая ситуация заставляет BinaryFormatter выдавать исключение.

[Serializable] 
class SerializeMe 
{ 
    public List<Data> _dataList; 
    public string _name; 
} 

[Serializable] 
class Data 
{ 
    public int _t; 
} 

Imagine SerializeMe сегодня сериализуется. Завтра мы решили, что нам больше не нужен класс Data и удалим его. Соответственно, мы модифицируем класс SerializeMe для удаления списка. В настоящее время невозможно десериализовать старую версию объекта SerializeMe.

Решение должно либо создать пользовательский BinaryFormatter, чтобы должным образом игнорировать дополнительные классы, либо сохранить класс Data с пустым определением (нет необходимости хранить элемент List).

Смежные вопросы