SerializationException при сериализации большого количества объектов в.NET

Похоже, на этот вопрос ответили все готово, но я все равно отправлю свой ввод.

Я знаю, когда мне нравится использовать самоисполняемые функции.

var myObject = {
    childObject: new function(){
        // bunch of code
    },
    objVar1: <value>,
    objVar2: <value>
}

Функция позволяет мне использовать дополнительный код для определения атрибутов и свойств childObjects для более чистого кода, например, для установки обычно используемых переменных или выполнения математических уравнений; Ой! или проверка ошибок. в отличие от ограничений на синтаксис инстанцирования вложенных объектов ...

object: {
    childObject: {
        childObject: {<value>, <value>, <value>}
    }, 
    objVar1: <value>,
    objVar2: <value>
}

В кодировании вообще есть много неясных способов сделать много одинаковых вещей, заставив вас задаться вопросом: «Зачем беспокоиться? " Но новые ситуации продолжают появляться там, где вы больше не можете полагаться только на основных / основных директоров.

21
задан Wilka 3 April 2009 в 09:05
поделиться

7 ответов

Я попытался воспроизвести проблему, но выполнение кода занимает вечность, даже если каждый из 13 миллионов объектов занимает всего 2 байта. Поэтому я подозреваю, что вы могли бы не только решить проблему, но и значительно улучшить производительность, если вы упакуете свои данные немного лучше в своих пользовательских реализациях ISerialize. Не позволяйте сериализатору так глубоко проникнуть в вашу структуру, но обрежьте его в тот момент, когда ваш объектный граф разбивается на сотни тысяч элементов массива или более (потому что, по-видимому, если у вас столько объектов, они довольно малы иначе ты не сможешь хранить их в памяти). Возьмите этот пример, который позволяет сериализатору видеть классы B и C, но вручную управляет коллекцией класса A:

class Program
{
    static void Main(string[] args)
    {
        C c = new C(8, 2000000);
        System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        bf.Serialize(ms, c);
        ms.Seek(0, System.IO.SeekOrigin.Begin);
        for (int i = 0; i < 3; i++)
            for (int j = i; j < i + 3; j++)
                Console.WriteLine("{0}, {1}", c.all[i][j].b1, c.all[i][j].b2);
        Console.WriteLine("=====");
        c = null;
        c = (C)(bf.Deserialize(ms));
        for (int i = 0; i < 3; i++)
            for (int j = i; j < i + 3; j++)
                Console.WriteLine("{0}, {1}", c.all[i][j].b1, c.all[i][j].b2);
        Console.WriteLine("=====");
    }
}

class A
{
    byte dataByte1;
    byte dataByte2;
    public A(byte b1, byte b2)
    {
        dataByte1 = b1;
        dataByte2 = b2;
    }

    public UInt16 GetAllData()
    {
        return (UInt16)((dataByte1 << 8) | dataByte2);
    }

    public A(UInt16 allData)
    {
        dataByte1 = (byte)(allData >> 8);
        dataByte2 = (byte)(allData & 0xff);
    }

    public byte b1
    {
        get
        {
            return dataByte1;
        }
    }

    public byte b2
    {
        get
        {
            return dataByte2;
        }
    }
}

[Serializable()]
class B : System.Runtime.Serialization.ISerializable
{
    string name;
    List<A> myList;

    public B(int size)
    {
        myList = new List<A>(size);

        for (int i = 0; i < size; i++)
        {
            myList.Add(new A((byte)(i % 255), (byte)((i + 1) % 255)));
        }
        name = "List of " + size.ToString();
    }

    public A this[int index]
    {
        get
        {
            return myList[index];
        }
    }

    #region ISerializable Members

    public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
    {
        UInt16[] packed = new UInt16[myList.Count];
        info.AddValue("name", name);
        for (int i = 0; i < myList.Count; i++)
        {
            packed[i] = myList[i].GetAllData();
        }
        info.AddValue("packedData", packed);
    }

    protected B(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
    {
        name = info.GetString("name");
        UInt16[] packed = (UInt16[])(info.GetValue("packedData", typeof(UInt16[])));
        myList = new List<A>(packed.Length);
        for (int i = 0; i < packed.Length; i++)
            myList.Add(new A(packed[i]));
    }

    #endregion
}

[Serializable()]
class C
{
    public List<B> all;
    public C(int count, int size)
    {
        all = new List<B>(count);
        for (int i = 0; i < count; i++)
        {
            all.Add(new B(size));
        }
    }
}
10
ответ дан 29 November 2019 в 22:07
поделиться

Вы думали о факте это Int32. MaxValue 2,147,483,647 - более чем 2 миллиарда.

Вам были бы нужны 16 ГБ памяти только для хранения указателей (принимающий машину на 64 бита), уже не говоря о самих объектах. Половина этого на машине на 32 бита, хотя сжимая 8 ГБ данных указателя максимум приблизительно в 3 ГБ применимое пространство была бы хорошим приемом.

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

Рассмотрите этот простой класс:

public class Node
{
    public string Name {get; set;}
    public IList<Node> Children {get;}
    public Node Parent {get; set;}
    ...
}

Этот простой класс не может быть сериализирован, потому что присутствие свойства Parent означает, что сериализация войдет в бесконечный цикл.

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

Одна техника, которая часто используется, состоит в том, чтобы сохранить имя (или идентификатор) ссылочного объекта вместо фактической ссылки, разрешив имя назад к объекту на загрузке.

1
ответ дан 29 November 2019 в 22:07
поделиться

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

1
ответ дан 29 November 2019 в 22:07
поделиться

Я предполагаю... сериализируют меньше объектов за один раз?

2 основных вопроса:

  • , какие объекты - они?
    • ПОСТЕПЕННО?
    • DataTable?
  • , какая сериализация - это?
    • xml? <ул.> <литий> XmlSerializer? <литий> DataContractSerializer?
    • двоичный файл? <ул.> <литий> BinaryFormatter? <литий> SoapFormatter?
    • другой? <ул.> <литий> json? <литий> означал?

Сериализация должна иметь приблизительно рассмотрение того, каков объем данных; например, некоторая потоковая передача поддержки платформ сериализации и объектов и сериализированных данных, вместо того, чтобы полагаться на полный граф объектов или временное хранение.

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

Так: каков сценарий здесь?

0
ответ дан 29 November 2019 в 22:07
поделиться

Кажется, что Вы столкнулись с внутренним ограничением в платформе. Вы могли записать свою собственную сериализацию с помощью BinaryReader / Писатель или DataContractSerializer или что бы то ни было, но это не идеально, я знаю.

0
ответ дан 29 November 2019 в 22:07
поделиться

Чувак, Вы достигли конца .NET!

я не поразил этот предел, но здесь являюсь несколькими указателями:

  1. использование [XmlIgnore] для пропуска некоторых объектов - возможно, Вы не должны сериализировать все

  2. , Вы могли использовать сериализатор вручную (т.е. не с атрибутами, а реализацией Сериализируют ()), и разделите модели в большее количество файлов.

0
ответ дан 29 November 2019 в 22:07
поделиться

Необходимо ли выбрать все данные одновременно? Тринадцать миллионов объектов являются большой информацией для обработки сразу.

Вы могли реализовать механизм подкачки страниц и выбрать данные в меньших блоках. И это могло бы повысить оперативность реагирования приложения, так как Вы не должны будете ожидать всех тех объектов закончить сериализировать.

0
ответ дан 29 November 2019 в 22:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: