Похоже, на этот вопрос ответили все готово, но я все равно отправлю свой ввод.
Я знаю, когда мне нравится использовать самоисполняемые функции.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
Функция позволяет мне использовать дополнительный код для определения атрибутов и свойств childObjects для более чистого кода, например, для установки обычно используемых переменных или выполнения математических уравнений; Ой! или проверка ошибок. в отличие от ограничений на синтаксис инстанцирования вложенных объектов ...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
В кодировании вообще есть много неясных способов сделать много одинаковых вещей, заставив вас задаться вопросом: «Зачем беспокоиться? " Но новые ситуации продолжают появляться там, где вы больше не можете полагаться только на основных / основных директоров.
Я попытался воспроизвести проблему, но выполнение кода занимает вечность, даже если каждый из 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));
}
}
}
Вы думали о факте это 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% пути к решению этого - просто необходимо удостовериться, чтобы Вы удалили любые циклы из графа объектов, который Вы храните, для хранения дерева объектов вместо этого.
Одна техника, которая часто используется, состоит в том, чтобы сохранить имя (или идентификатор) ссылочного объекта вместо фактической ссылки, разрешив имя назад к объекту на загрузке.
В зависимости от структуры данных, возможно, вы можете сериализовать / десериализовать подграфы ваш большой граф объектов? Если бы данные могли быть каким-то образом разделены, вы могли бы избежать этого, создавая лишь небольшое дублирование сериализованных данных.
Я предполагаю... сериализируют меньше объектов за один раз?
2 основных вопроса:
Сериализация должна иметь приблизительно рассмотрение того, каков объем данных; например, некоторая потоковая передача поддержки платформ сериализации и объектов и сериализированных данных, вместо того, чтобы полагаться на полный граф объектов или временное хранение.
Другая опция состоит в том, чтобы сериализировать гомогенные наборы данных, а не полных графиков - т.е. сериализировать всех "клиентов" отдельно "заказы"; это обычно уменьшало бы объемы, за счет наличия большей сложности.
Так: каков сценарий здесь?
Кажется, что Вы столкнулись с внутренним ограничением в платформе. Вы могли записать свою собственную сериализацию с помощью BinaryReader / Писатель или DataContractSerializer или что бы то ни было, но это не идеально, я знаю.
Чувак, Вы достигли конца .NET!
я не поразил этот предел, но здесь являюсь несколькими указателями:
использование [XmlIgnore] для пропуска некоторых объектов - возможно, Вы не должны сериализировать все
, Вы могли использовать сериализатор вручную (т.е. не с атрибутами, а реализацией Сериализируют ()), и разделите модели в большее количество файлов.
Необходимо ли выбрать все данные одновременно? Тринадцать миллионов объектов являются большой информацией для обработки сразу.
Вы могли реализовать механизм подкачки страниц и выбрать данные в меньших блоках. И это могло бы повысить оперативность реагирования приложения, так как Вы не должны будете ожидать всех тех объектов закончить сериализировать.