XML против двоичной производительности для сериализации / десериализации

Я работаю над компактным каркасным приложением, и мне нужно повысить производительность. В настоящее время приложение работает в автономном режиме, выполняя сериализацию объектов в XML и сохраняя их в базе данных. Используя инструмент профилирования, я мог видеть, что это было довольно большой нагрузкой, замедляющей работу приложения. Я думал, что если я переключусь на двоичную сериализацию, производительность увеличится, но поскольку это не поддерживается в компактной среде, я посмотрел на protobuf-net. Сериализация кажется более быстрой, но десериализация намного медленнее, и приложение выполняет больше десериализации, чем сериализации.

Должна ли двоичная сериализация быть быстрее, и если да, что я могу сделать, чтобы повысить производительность? Вот фрагмент того, как я использую и XML, и бинарный файл:

XML сериализация:

public string Serialize(T obj)
{
  UTF8Encoding encoding = new UTF8Encoding();
  XmlSerializer serializer = new XmlSerializer(typeof(T));
  MemoryStream stream = new MemoryStream();
  XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8);
  serializer.Serialize(stream, obj);
  stream = (MemoryStream)writer.BaseStream;
  return encoding.GetString(stream.ToArray(), 0, Convert.ToInt32(stream.Length));
}
public T Deserialize(string xml)
{
  UTF8Encoding encoding = new UTF8Encoding();
  XmlSerializer serializer = new XmlSerializer(typeof(T));
  MemoryStream stream = new MemoryStream(encoding.GetBytes(xml));            
  return (T)serializer.Deserialize(stream);
}

Бинарная сериализация Protobuf-net:

public byte[] Serialize(T obj)
{
  byte[] raw;
  using (MemoryStream memoryStream = new MemoryStream())
  {
    Serializer.Serialize(memoryStream, obj);
    raw = memoryStream.ToArray();
  }

  return raw;            
}

public T Deserialize(byte[] serializedType)
{
  T obj;
  using (MemoryStream memoryStream = new MemoryStream(serializedType))
  {
    obj = Serializer.Deserialize<T>(memoryStream);
  }
  return obj;
}

Ответы на вопрос(6)

Основным расходом в вашем методе является фактическая генерация класса XmlSerializer. Создание сериализатора - это длительный процесс, который вы должны выполнять только один раз для каждого типа объекта. Попробуйте кэшировать сериализаторы и посмотреть, не улучшит ли это вообще производительность.

Следуя этому совету, я увидел значительное улучшение производительности своего приложения, что позволило мне продолжать использовать сериализацию XML.

Надеюсь это поможет.

XML часто медленно обрабатывается и занимает много места. Было предпринято несколько различных попыток решить эту проблему, и наиболее популярной сегодня, похоже, является просто сбросить пакет в файл gzip, как в случае сКонвенция об открытой упаковке.

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

Я собираюсь исправить себя, Марк Гравалл отметил, что на первой итерации накладывается нагрузка на модель, поэтому я провел несколько тестов, в которых принималось в среднем 1000 итераций сериализации и десериализации как для XML, так и для двоичного кода. Я попробовал свои тесты с v2 из Compact Framework DLL, а затем с v3.5 DLL. Вот что я получил, время в мс:

.NET 2.0
================================ XML ====== Binary ===
Serialization 1st Iteration      3236       5508
Deserialization 1st Iteration    1501       318
Serialization Average            9.826      5.525
Deserialization Average          5.525      0.771

.NET 3.5
================================ XML ====== Binary ===
Serialization 1st Iteration      3307       5598
Deserialization 1st Iteration    1386       200
Serialization Average            10.923     5.605
Deserialization Average          5.605      0.279

Производительность снижается при сериализации объектов или записи их в базу данных? Поскольку их написание, вероятно, затрагивает какое-то медленное хранение, я полагаю, что это гораздо больший перфомент, чем этап сериализации.

Имейте в виду, что измерения производительности, опубликованные Marc Gravell, тестируют производительность более 1 000 000 итераций.

В какой базе данных вы храните их? Сериализуются ли объекты в памяти или прямо в хранилище? Как их отправляют в БД? Насколько большие объекты? При обновлении отправляете ли вы все объекты в базу данных или только тот, который изменился? Вы вообще что-то кешируете в памяти или перечитываете из памяти каждый раз?

Интересные ... мысли

  • what version of CF is this; 2.0? 3.5? In particular, CF 3.5 has Delegate.CreateDelegate that allows protobuf-net to access properties much faster than in can in CF 2.0
  • are you annotating fields or properties? Again, in CF the reflection optimisations are limited; you can get beter performance in CF 3.5 with properties, as with a field the only option I have available is FieldInfo.SetValue

Есть ряд других вещей, которые просто не существуют в CF, поэтому он должен идти на компромиссы в нескольких местах. Для слишком сложных моделей есть такжеизвестная проблема с ограничениями дженериков CF, Исправление идет полным ходом, но этоbig изменить, и занимает "некоторое время".

Для информации, некоторые метрики на обычном (полном) .NET сравнивают различные форматы (включаяXmlSerializer и протобуф-нет)здесь.

Вы пытались создать собственные классы сериализации для ваших классов? Вместо использования XmlSerializer, который является сериализатором общего назначения (он создает группу классов во время выполнения). Есть инструмент для этого (sgen). Вы запускаете его во время процесса сборки, и он генерирует пользовательскую сборку, которую можно использовать в темпе XmlSerializer.

Если у вас есть Visual Studio, этот параметр доступен на вкладке «Построение» свойств вашего проекта.

Ваш ответ на вопрос