C#对象数组,非常大,寻找更好的方法

时间:2011-02-15 08:32:37

标签: c# .net

好的,所以在我的一个项目中,我试图重新制作存储某些变量的方式,我有一个简单的对象数组。这些对象引用的类是:

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

我计划向它添加更多内容,在当前类类型中是对象的当前值,而lastblock是对象的用途。

我像这样创建数组:

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兆的ram(我的不要,因为134217728字节应该在134兆左右......对吗?)。令我感到困惑的是,对象引用可以产生更多的内存使用。

我做错了什么,或者我应该回到原来的方式?我希望对象引用只是因为它意味着我的所有变量都在1个数组中,而不是在4个独立的数组中,似乎就好像它对系统更好。

编辑:

经过几种不同的方式,我发现改变了

class Blocks

struct Blocks

创造了一个与众不同的世界,感谢社区提供未来使用的欢迎提示,遗憾的是我不想在结构中添加两个字节并将其调用完成,这就是我停下来测试我的设计和伤口的地方原来的问题。在结构中添加任何其他内容之后(至少在我的列表中的任何其他内容,意味着播放器对象引用或播放器名称字符串。)它会导致内存不足异常,这意味着我将无法毕竟使用这个系统。

但是如何做到这一点的知识将来会非常有用。为此,再次感谢你。

6 个答案:

答案 0 :(得分:4)

以下是我尝试使用结构类型而不是类类型

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 Mb的RAM。

如果可能,请尝试 struct

答案 1 :(得分:1)

您可以使用List类来管理无限数量的对象。请查看我提供的链接。您可以将无限(理论上)理想数量的对象添加到列表中。

使用列表,您可以轻松地按索引访问任何项目。它还具有搜索,排序和操作其中包含的对象的方法。

如果您使用列表,您的代码将看起来如下 -

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
}

您可以找到列表中包含的对象的任何特定索引。请参阅此method example

因此,使用列表,您将能够以统一的方式轻松管理大量对象。

要了解详情,请转到here

答案 2 :(得分:0)

请阅读:Object Overhead: The Hidden .NET Memory Allocation Cost

您的对象的总成本类似于16个字节(在32位系统上)。 (“标题”为8个字节,字段为4个字节,参考为4个字节)和512 * 512 * 512 * 16 = 2.1gb: - )

但你可能是64位系统,所以它是16 + 8 + 8 = 28,所以4.29gb

答案 3 :(得分:0)

您应该考虑使用“struct”而不是“class”。

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

“结构类型适用于表示轻量级对象,如Point,Rectangle和Color。尽管可以将点表示为类,但在某些情况下结构更有效。例如,如果声明了1000个Point对象的数组,你将为引用每个对象分配额外的内存。在这种情况下,结构更便宜。“

如果您尝试,请发布您的搜索结果。

答案 4 :(得分:0)

创建数组时,还要在每个单元格上实例化一个块。你真的需要这样做吗?

blocks[i] = new Blocks();

如果不实例化Blocks,则只需要一个空引用数组。在访问代码中,您可以检查null并返回默认值。这些方面的东西:

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

写入时还要检查是否有,如果没有,请先创建它。这应该可以节省大量内存。

使用锯齿状数组或嵌套列表也应该有很多帮助。

关心GJ

答案 5 :(得分:0)

结构是前进的方向,并且会开启使用不安全的代码/指针算法进行优化的可能性

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++;
    }
}

当然有人会来,说可变的结构是邪恶的! (只有你不知道如何使用它们)