繁体   English   中英

为什么一个类的数组比结构数组消耗的内存多20%?

[英]Why does an array of classes consume ~20% more memory than array of structs?

我正在制作一个2D平台游戏并代表我正在使用2D数组的瓦片,这些瓦片是具有位置,类型和各种标志字段的类。 当我将tile类中的class关键字更改为struct ,加载的地图消耗的内存减少约20%。

我不知道这个动作的正确与否,我只是想知道为什么内存消耗的差异。

编辑:数字为1038 MB,瓦片为类,845 MB为结构(没有大部分游戏数据)。

对象数组实际上是一个引用数组,对象存储在堆上。

这意味着引用有4或8个字节的开销(取决于x86或x64),然后堆上的每个对象都有8或16个字节的开销。

在结构数组中,struct值直接存储在数组中,因此不会产生额外的开销。

因此,如果您的数据是例如48个字节,则额外的12个字节(在x86模式下)将是所用总内存的20%的开销。

请注意,它们的使用方式也有所不同。 如果您移动切片或将其作为参数发送到方法,则在使用结构时将复制所有数据,但如果使用类,则仅复制引用。 如果你可以保持结构小于16个字节,性能差异很小,但如果它更大,你可以通过使用类来获得更快的代码。

每个对象都有一个8字节的头,其中包含指向类型句柄和同步块索引的指针,而结构是内联分配的。 此外,您需要为正在使用的每个引用类型变量分配指针大小的引用。

本文将详细介绍如何在运行时创建对象。

结构类型的存储位置(变量,参数,数组元素或字段)包含其所有公共字段和私有字段的值,通常是连接的,但可能包含一些填充。 类类型的存储位置保存对堆对象(可能为空)的引用(4-8个字节)。 堆对象保存8-16个字节的开销,以及对象及其祖先持有的所有公共,受保护和私有字段的内容。

如果要存储的内容是固定大小的值包,则应该使用具有公开字段的结构。 结构应该是不可变的概念可以追溯到C#编译器将采用一段代码的日子:

readonly Point Pt = new Point(3,4);
  void Yippie() { Pt.X += 5; }

并让Yippie构造一个新的临时Point ,将Pt复制到它,在该临时实例上调用X属性setter,然后丢弃它。 有人认为防止这种无意义的正确方法是不要让编译器说“抱歉 - 你不能在只读结构变量上调用属性设置器”,而是定义结构以便具有只读属性没有二传手。 已经做了正确的事情本来可以要求其将要发生变异的任何结构的方法或属性this在他们的声明中如此表示,禁止使用在只读结构这样的方法或属性。

在属性中包装struct字段会影响性能,我建议不要使用它,除非需要强制执行struct invariants。 我也建议避免一个声明结构readonly ,因为这样声明的结构将在任何领域的全面访问任何时候都可以复制。

. 顺便提一下,要注意可变类类型是一件重要的事情:可变类对象的状态不仅包括其字段的内容,还包括它所 在某些情况下,这可能很有用。 通常,防止严重头痛的唯一方法是让持有可变对象引用的实体避免共享此类引用。 如果创建一个类类型的东西需要额外的工作来防止引用被滥用,这是一个好的迹象,有问题的类型应该是一个结构。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM