C # массив объектов, очень большой, ищет лучший способ - PullRequest
1 голос
/ 15 февраля 2011

Хорошо, так что в одном из моих проектов, я пытаюсь переделать способ хранения определенных переменных, у меня есть простой массив объектов. Класс, к которому относятся эти объекты:

class Blocks
{
    public byte type = Block.Empty;
    byte lastblock = Block.Zero;
}

Я планирую добавить к нему больше, в текущем типе класса указано текущее значение объекта, а в последнем блоке указано, каким был объект.

Я создаю массив следующим образом:

blocks = new Blocks[width * depth * length];

for (int i = 0; i < ((width * length) * depth); i++)
{
    blocks[i] = new Blocks();
}

Проблема, с которой я столкнулся, заключается в том, что когда я создаю очень большой массив (512,512,512 или 134217728 для тех из вас, кто не любит математику), массив становится огромным, свыше 3,5 гигабайт.

Старый способ создания этого массива был немного проще, но гораздо сложнее расширить, он просто создал массив байтов, представляющих текущий блок, и, похоже, использует только 2 мегабайта оперативной памяти, когда он действительно загружен (который я не получается, поскольку 134217728 байт должны составлять около 134 мегабайт ... верно?). Это просто сбивает с толку, что ссылки на объекты могут генерировать гораздо больше использования оперативной памяти.

Я делаю что-то не так или мне просто вернуться к старому способу, которым это было сделано? Я хотел бы, чтобы ссылки на объекты просто потому, что это означает, что все мои переменные находятся в 1 массиве, а не в 4 отдельных массивах, которые кажутся , как если бы это было лучше для системы.

EDIT:

Проработав несколько разных способов сделать это, я обнаружил, что изменение

class Blocks

до

struct Blocks

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

Но знание того, как это сделать, будет весьма полезно в будущем. За это еще раз спасибо.

Ответы [ 6 ]

4 голосов
/ 15 февраля 2011

Вот что я попробовал с типом структуры вместо типа класса :

public struct Block
{
    public byte _current;
    public byte _last;
}

public static void RunSnippet()
{
    Block[] blocks = new Block[512 * 512 * 512];

    for (int i = 0; i < ((512 * 512) * 512); i++)
    {
        blocks[i] = new Block();
    }
}

Фрагмент запустился почти мгновенно и съел около 267 МБ ОЗУ.

Так что дайте struct попробовать, если это возможно.

1 голос
/ 15 февраля 2011

Вы можете использовать Список класс для управления неограниченным количеством объектов. Пожалуйста, посмотрите на ссылку, которую я предоставил. Вы можете добавить бесконечное (ну, теоретически) количество объектов в список.

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

Если вы используете список, ваш код будет выглядеть примерно так:

List<Blocks> blocks = new List<Blocks>();

for (int i = 0; i < ((width * length) * depth); i++)  // The amount of items that you want to add
{
    Blocks b = new Blocks();
    blocks.Add(b);
}

Вы можете получить доступ к каждому элементу в этом списке следующим образом -

foreach(Blocks b in blocks)
{
    // You have the object, do whatever you want
}

Вы можете найти любой конкретный индекс объекта, содержащийся в списке. Посмотрите этот пример метода .

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

Чтобы узнать больше, зайдите здесь .

0 голосов
/ 15 февраля 2011

Структуры - это путь вперед и открывают возможность оптимизации с небезопасной арифметикой кода / указателя

struct Block
{
    byte Current;
    byte Last;
}

Block[] blocks = new Block[512 * 512 * 512];

unsafe
{
    Block* currentBlock = &blocks;

    for (int i = 0; i < (512 * 512) * 512; i++)
    {
        currentBlock->Current = 0xff;
        currentBlock->Last = 0x00;

        currentBlock++;
    }
}

Конечно, кто-то придет и скажет, что изменчивые структуры - это зло! (Только если вы не знаете, как их использовать)

0 голосов
/ 15 февраля 2011

Когда вы создаете массив, вы также создаете экземпляр Blocks в каждой ячейке.Вам действительно нужно это сделать?

blocks[i] = new Blocks();

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

if(blocks[i,j] == null)  return new  Blocks();
else return blocks[i,j];

При написании также проверьте, есть ли такой, если нет, сначала создайте его.Это должно сэкономить много памяти.

Использование зубчатых массивов или вложенных списков также должно помочь.

С уважением, GJ

0 голосов
/ 15 февраля 2011

Вы должны рассмотреть использование "struct" вместо "class".

http://msdn.microsoft.com/en-us/library/ah19swz4(v=vs.71).aspx

"Тип структуры подходит для представления легких объектов, таких как Point, Rectangle и Color. Хотя можно представить точку в виде класса, структура в некоторых сценариях более эффективна. Например, если вы объявляете массив из 1000 объектов Point, вы будете выделять дополнительную память для ссылки на каждый объект. В этом случае структура дешевле. "

Пожалуйста, опубликуйте свои результаты, если вы попробуете.

0 голосов
/ 15 февраля 2011

Прочитайте это: Служебные объекты: скрытая стоимость выделения памяти .NET .

Общая стоимость вашего объекта составляет около 16 байт (в 32-битной системе). (8 байтов для "заголовка", 4 байта для ваших полей, 4 для справки) И 512 * 512 * 512 * 16 = 2.1gb: -)

Но вы, вероятно, в 64-битной системе, так что это 16 + 8 + 8 = 28, поэтому 4.29gb.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...