在C#/ .NEt动态类型占用的空间比对象少吗?

Jef*_*ron 10 c# memory boxing unboxing dynamic

我有一个控制台应用程序,允许用户指定要处理的变量.这些变量有三种形式:string,double和long(目前最常用的类型是double和long).用户可以指定他们喜欢的任何变量以及任何顺序,因此我的系统必须能够处理它.为此,在我的应用程序中,我将这些存储为对象,然后根据需要转换/取消它们.例如:

public class UnitResponse
{
    public object Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的理解是盒装对象比标准值类型占用更多的内存(大约12个字节).

我的问题是:使用dynamic关键字存储这些值会更有效吗?它可能解决装箱/拆箱问题,如果效率更高,这会影响性能吗?

编辑

为了提供一些上下文并防止"你确定你使用足够的RAM担心这个",在我最糟糕的情况下,我需要担心420,000,000个数据点(60个变量*7,000,000个记录).这是我保留的关于每个变量的一堆其他数据(包括一些布尔值等).因此减少内存会产生巨大影响.

Eri*_*ert 19

好的,所以真正的问题是"我有一个非常庞大的数据集,我将其存储在内存中,如何在时间和内存空间中优化其性能?"

几点想法:

  • 你是绝对正确的仇恨和恐惧拳击.拳击费用很高.首先,是的,盒装对象会占用额外的内存.其次,盒装对象存储在堆上,而不是存储在堆栈或寄存器中.第三,他们是垃圾收集; 这些对象中的每一个都必须在GC时间被查询,以查看它是否包含对另一个对象的引用,它永远不会,并且这是GC线程上的大量时间.你几乎肯定需要做一些事来避免拳击.

动态不是它; 这是拳击加上一大堆其他开销.(与其他动态调度系统相比, C#的动态速度非常快,但绝对值并不快或很小).

这很糟糕,但你可以考虑使用一个结构,它的布局在各个领域之间共享内存 - 比如C中的联合.这样做确实非常严重,根本不安全,但它可以在这些情况下提供帮助.在网上搜索"StructLayoutAttribute"; 你会找到教程.

  • 真的,长,双或串?不能是int,float还是string?数据是否确实超过数十亿或精确到15位小数?对于99%的案例,int和float不会完成这项工作吗?它们只有一半大小.

通常我不建议使用浮动超过双倍,因为它是虚假的经济; 当人们拥有一个数字时,人们常常以这种方式节约,就像四个字节的节省将会产生差异.4200万个浮标和4200万双打之间的差异是相当大的.

  • 您可以利用的数据是否有规律性?例如,假设您的4200万条记录中只有100000个实际值,例如,每个long,每个double的100000个值,以及每个字符串的100000个值.在这种情况下,您为long,double和字符串创建某种索引存储,然后每个记录获得一个整数,其中低位是索引,前两位指示将其取出的存储.现在你有4200万条记录,每条记录都包含一个int,并且这些值以一些非常紧凑的形式存储在其他地方.

  • 将布尔值存储为一个字节中的位; 写属性来进行位移以获得它们.用这种方式保存自己几个字节.

  • 请记住,内存实际上是磁盘空间; RAM只是一个方便的缓存.如果数据集太大而无法保存在RAM中,那么有些东西会将其重新登录到磁盘并在以后读取它; 可能是你或它可能是操作系统.您可能比操作系统更了解您的数据位置.您可以以一些方便的可分页形式(如b-tree)将数据写入磁盘,并且可以更有效地将内容保存在磁盘上,并且只在需要时将其带入内存.


Eri*_*ert 14

我想你可能在这里看错了.记住动态的作用.它在运行时再次启动编译器.它为编译器加载了数十万字节的代码,然后在每个调用站点发出缓存,其中包含每个动态操作的新发送的IL的结果.你花费了几十万字节来节省八个字节.这似乎是一个坏主意.

当然,你不保存任何东西."动态"只是一个带有花哨帽子的"对象"."动态"对象仍然是盒装的.

  • @Jeffrey:我引用了C#4规范的4.7节,其中指出"在运行时类型动态与对象无法区分". (2认同)