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

时间:2011-01-27 23:33:40

标签: c# memory dynamic boxing unboxing

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

public class UnitResponse
{
    public object Value { get; set; }
}

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

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

修改

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

4 个答案:

答案 0 :(得分:19)

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

几点想法:

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

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

这很糟糕,但你可以考虑使用一个结构,它的布局在各个字段之间共享内存 - 比如C中的联合。这样做真的非常粗略根本不安全< / em>但它可以在这些情况下提供帮助。在网上搜索“StructLayoutAttribute”;你会找到教程。

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

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

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

  • 将布尔值作为位存储在一个字节中;写属性来进行位移以获得它们。通过这种方式节省几个字节。

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

答案 1 :(得分:14)

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

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

答案 2 :(得分:3)

没有。 dynamic如何执行对象的操作有关,而不是对象本身的存储方式。在这个特定的上下文中,值类型仍然是盒装的。

此外,所有这些努力真的值得每个对象12个字节吗?当然,除了节省几千字节(如果那样)的RAM之外,还有更好的用途吗?您是否证明您的程序使用RAM实际上是一个问题?

答案 3 :(得分:2)

没有。 Dynamic将它简单地存储为Object。

这可能是微观优化,几乎没有任何好处。如果这确实成为一个问题,那么你可以使用其他机制(泛型)来加快速度。