C#对象数组,非常大,寻找更好的方法
好吧,所以在我的一个项目中,我试图重新制作存储某些变量的方式,我有一个简单的对象数组。 这些对象引用的类是:
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兆左右……对吧?)。 令我感到困惑的是,对象引用可以产生更多的ram使用。
我做错了什么,或者我应该回到原来的做法? 我想对象引用只是因为它意味着我的所有变量都在1个数组中,而不是在4个独立的数组中,这似乎对系统来说更好。
编辑:
经过几种不同的方式,我发现了变化
class Blocks
至
struct Blocks
做了一个与众不同的世界,感谢社区提供未来使用的欢迎提示,遗憾的是我不想在结构中添加两个字节并将其调用完成,这就是我停下来测试我的设计并结束了原始问题。 在结构中添加任何其他内容(至少在我的列表中的任何其他内容,意味着播放器对象引用或播放器名称字符串。)它会导致内存不足exception,这意味着我将无法毕竟使用这个系统。
但是如何做到这一点的知识将来会非常有用。 为此,再次感谢你。
这是我尝试使用结构类型而不是类类型 :
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 。
您可以使用List类来管理无限数量的对象。 请看一下我提供的链接。 您可以在列表中添加无限(理论上)数量的对象。
使用列表,您可以轻松地按索引访问任何项目。 它还具有搜索,排序和操作其中包含的对象的方法。
如果你使用list,你的代码看起来有点像下面 –
List blocks = new List (); 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 }
您可以找到列表中包含的对象的任何特定索引。 请参阅此方法示例 。
因此,使用列表,您将能够以统一的方式轻松管理大量对象。
要了解更多信息,请转到此处 。
您应该考虑使用“struct”而不是“class”。
http://msdn.microsoft.com/en-us/library/ah19swz4(v=vs.71).aspx
“结构类型适用于表示轻量级对象,如Point,Rectangle和Color。尽管可以将点表示为类,但在某些情况下结构更有效。例如,如果声明数组为1000点对象,你将为引用每个对象分配额外的内存。在这种情况下,结构更便宜。“
如果您尝试,请发布您的结果。
创建arrays时,还可以在每个单元格上实例化块。 你真的需要那样做吗?
blocks[i] = new Blocks()
;
如果不实例化Blocks,则只需要一个空引用数组。 在访问代码中,您可以检查null并返回默认值。 这些方面的东西:
if(blocks[i,j] == null) return new Blocks(); else return blocks[i,j];
写入时还要检查是否有,如果没有,请先创建它。 这应该可以节省大量内存。
使用锯齿状数组或嵌套列表也应该有很多帮助。
关心GJ
结构是前进的方向,并且将开启使用不安全的代码/指针算法进行优化的可能性
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++; } }
当然有人会来,说可变的结构是邪恶的! (只有你不知道如何使用它们)
阅读: 对象开销:隐藏的.NET内存分配成本 。
您的对象的总成本类似于16个字节(在32位系统上)。 (8个字节用于“标题”,4个字节用于您的字段,4个用于参考)和512 * 512 * 512 * 16 = 2.1gb
🙂
但你可能是64位系统,所以它是16 + 8 + 8 = 28,所以4.29gb
。