Как сериализовать большие объекты в .NET?(Исключения из памяти)
-
22-08-2019 - |
Вопрос
Я использую сериализацию для функции "сохранить" в своем приложении.Но когда данные слишком большие (15 + МБ), я начинаю получать исключения OutOfMemory.
У меня так много объектов, и они связаны с другими маленькими объектами, я думаю, это приводит к слишком большой вычислительной мощности и хранению данных в памяти.
Мой код основан на этом, почти такой же:
http://www.codeproject.com/KB/vb/TreeViewDataAccess.aspx
Редактировать :
Я не использую пользовательскую сериализацию, все это делается с помощью атрибутов [Serialization].Исключая некоторые поля.
Я сериализую так много объектов и пользовательских классов.Включает в себя словарь, структуры и кучу других вещей.
Я сериализую его в файл.
Я использую XmlSerializer
P.S.У меня есть 4 ГБ физической памяти.
Решение
Благодаря ответам выяснилось, что моя проблема связана с XmlSerializer, и я избавился от нее.Двоичная сериализация отлично работает с теми данными, которые у меня есть.
Решение
15 МБ не должны давать вам ООМ.
Если данные имеют древовидный вид (а не полный график), вы могли бы рассмотреть сериализатор типа протобуф-сеть;помимо использования очень эффективного (как по скорости, так и по памяти) двоичного формата "буферов протокола" Google, он выигрывает от того, что ему не нужно выполнять отслеживание ссылок (требуется для графиков), что означает, что ему нужно беспокоиться о данных только один раз (дважды, если они должны быть буферизованы).
Однако для этого требуется другая разметка для ваших классов (или, по крайней мере, "opt in") - и она не будет обрабатывать полные графики.Но это есть, и бесплатно...
Другие советы
У меня была точно такая же проблема.Причина в том, что .NET сериализация не масштабируется.
Я решил проблему, используя превосходную библиотеку с открытым исходным кодом Саймона Хьюитта см. Оптимизация сериализации в .NET - часть 2.
Помимо значительного сокращения использования памяти, это также намного быстрее.Аналогично статье, я получил ускорение в 20 раз.
На самом деле, XmlSerializer игнорирует атрибуты SerializableAttribute .Они используются только классами форматирования (BinaryFormatter, SoapFormatter).
Я бы не стал сериализовать с помощью XmlSerializer, и особенно не стал бы использовать комбинацию XmlSerializer и BinaryFormatter.
Я бы просто попытался сериализовать все, используя BinaryFormatter .
Вы могли бы написать свои собственные процедуры сериализации и посмотреть, сможете ли вы получить какие-либо преимущества в производительности, вручную адаптировав свой процесс сериализации.Для получения более подробной информации смотрите Страница MSDN о пользовательской сериализации.
Может быть, вы могли бы рассказать нам немного подробнее о том, как производится сериализация.Используете ли вы пользовательскую сериализацию ?Или вы просто используете встроенный атрибут [Serialization] ?
Я думаю, что хороший способ для вас справиться с этим - попытаться выполнить свою пользовательскую логику сериализации и сериализовать только то, что вам нужно, это не может занимать 4 ГБ, в любом случае это также зависит от того, сколько памяти присвоено вашему приложению.
При всех упомянутых здесь подходах теряется простота выгрузки больших объектов на диск и восстановления.Кроме того, они поддерживают только типы данных дампа, поэтому вы не можете сбрасывать ссылочные типы так же легко, как могли бы с помощью BinaryFormatter.
Также выполняю сжатие с использованием gzip - файл или 7-Застежка-молния перед двоичным форматированием больших объектов фактически переместите размер выше 16 МБ на что-то вроде 32 МБ.
Вы могли бы скачать JSON.NET Библиотека, которая работает в моем проекте для сериализации и десериализации данных объемом более 100 МБ.
Для сериализации вы можете работать следующим образом
Если у вас есть объект, используйте TextWriter
using (TextWriter textWriter = File.CreateText("LocalJsonFile.json"))
{
var serializer = new JsonSerializer();
serializer.Serialize(textWriter , yourObject);
}
Если у вас есть строка, используйте StringWriter
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
using(JsonWriter textWriter = new JsonTextWriter(sw))
{
var serializer = new JsonSerializer();
serializer.Serialize(textWriter, yourObject);
}
Это может сработать для вас.