2012-02-09 3 views
2

Я пишу приложение, которое создаст тысячи мелких объектов и сохранит их рекурсивно в массиве. «Рекурсивно» я имею в виду, что каждый экземпляр K будет иметь массив экземпляров K, который будет иметь и массив экземпляров K и т. Д., И этот массив + одно int-поле являются единственными свойствами + некоторые методы. Я обнаружил, что использование памяти растет очень быстро даже для небольшого количества данных - около 1 МБ), а когда данные, которые я обрабатываю, составляют около 10 МБ, я получаю «OutOfMemoryException», не говоря уже о том, когда он больше (у меня 4 ГБ ОЗУ) :). Итак, что вы предлагаете мне делать? Я полагал, что если бы я создал отдельный класс V для обработки этих объектов, так что экземпляры K имели бы только массив из K + одно целочисленное поле и делали бы K как структуру, а не класс, он должен немного оптимизировать вещи - никакой сборки мусора и прочее ... Но это немного сложная задача, поэтому я скорее спрошу вас, хорошая ли это идея, прежде чем я начну переписывать :).Struct vs class memory overhead

EDIT: Ok, некоторые абстрактный код

public void Add(string word) { 
    int i; 
    string shorter; 

    if (word.Length > 0) { 
     i = //something, it's really irrelevant 

     if (t[i] == null) { 
      t[i] = new MyClass(); 
     } 

     shorterWord = word.Substring(1); 

     //end of word 
     if(shorterWord.Length == 0) { 
      t[i].WordEnd = END; 
     } 

     //saving the word letter by letter 
     t[i].Add(shorterWord); 
     } 
    } 
} 

ответ

4

Для меня, когда я углублялся в это, у меня были следующие предположения (они могут быть неточными, я старею для программиста). Класс имеет дополнительное потребление памяти, потому что для его устранения требуется ссылка. Сохраните ссылку, а указатель Int32 необходим для 32-битного компиляции. Выделяется всегда в куче (не помню, имеет ли C++ другие возможности, я бы рискнул да?)

Короткий ответ, найденный в этой статье, Объект имеет базовый размер 12 байтов + 4, возможно, неиспользуемые байты в зависимости от вашего класса (без сомнения, что-то делать с дополнением).

http://www.codeproject.com/Articles/231120/Reducing-memory-footprint-and-object-instance-size

Другие вопросы, вы будете работать в эти Массивы также накладные расходы. Возможность заключается в том, чтобы управлять своим собственным смещением в большем массиве или массивах. Что, в свою очередь, приближается к чему-то более подходящему языку.

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

Я использую Structs, управляю вашим собственным смещением в большом массиве и использую правильные инструкции по упаковке, если он вам обслуживает (хотя я подозреваю, что это происходит при стоимости выполнения нескольких дополнительных инструкций при каждом обращении неравномерно упакован данные)

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
0

Убедитесь, что у вас достаточно памяти в вашей системе. Более 100mb + и т. Д. Это действительно зависит от вашей системы. Связанный список, рекурсивные объекты - это то, что вы смотрите. Если вы продолжаете рекурсивно, он достигнет предела памяти, и будет проигнорировано номиментозное исключение. Убедитесь, что вы отслеживаете использование памяти в любой программе. Ничто не ограничено, особенно память. Если память ограничена, сохраните ее на диск.

Похоже, что в вашем коде бесконечная рекурсия и из памяти выбрасывается. Проверьте код. Рекурсивный код должен начинаться и заканчиваться. В противном случае в какой-то момент он перейдет через 10 терабайтов.

+0

О нет, есть конец в моем коде, только это может занять некоторое время, прежде чем программа достигает ее ... –

+0

Если есть рекурсии в коде, должно быть концом. Иначе это будет продолжаться вечно и потребует неограниченного количества ресурсов. Убедитесь, что ваши массивы и рекурсия останавливаются в какой-то момент. Проблема здесь кажется, что ваш код продолжается вечно. – iefpw

0

Просто перечислите свой рекурсивный алгоритм и дезинформируйте имена переменных. Если вы выполняете тип обхода BFS и сохраняете все объекты в памяти, у вас закончится mem. Например, в этом случае замените его на DFS.

Edit 1:

Вы можете ускорить Algo путем оценки того, сколько элементов вы будете генерировать то выделить, что много памяти сразу. По мере продвижения алгоритма заполните выделенную память. Это уменьшает фрагментацию и перераспределение & операции копирования на полный массив. Тем не менее, после того, как вы закончите работу над этими сгенерированными словами, вы должны удалить их из своей структуры данных, чтобы они могли быть GC-ed, чтобы вы не исчерпали память.

+0

Можете ли вы просветить меня, пожалуйста ... BFS/DFS? –

+0

Я не делаю обход типа BFS. Пример: у вас есть слово «asdf» - получите первое письмо, упакуйте его в экземпляр K (под индексом 0), сделайте то же самое на вновь созданном экземпляре, передав ему строку «sdf». Если следующее слово для добавления будет «asdg», то первые три буквы будут пропущены, потому что thay уже существует, и только «g» добавляется как другая ветвь после «d» –

+2

@Myles, мне было любопытно, так что я googled it : http://en.wikipedia.org/wiki/Depth-first_search, http://en.wikipedia.org/wiki/Breadth-first_search. Я * думаю * это то, о чем говорит Эдриан. –

0

Вы можете использовать лучшую структуру данных i.e каждая буква может быть байтом (a-0, b-1 ...). каждый фрагмент слова может быть проиндексирован и особенно подстроки - вам следует уйти со значительно меньшим объемом памяти (хотя штраф за производительность)

2

Ваш стек взрывается.

Сделайте это итеративно вместо рекурсивно.

Вы не взорвали системный стек, выдувая стек кода, вызовы функций 10K выдувают его из воды.

Вам нужна правильная рекурсия хвоста, которая является просто итеративным взломом.

+1

Слова не так уж долго;) –