10

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

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

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

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

编辑

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

4

4 回答 4

19

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

几个想法:

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

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

这很恶心,但您可以考虑使用一个结构,其布局在各个字段之间共享内存——比如 C 中的联合。这样做真的很恶心,而且一点也不安全,但它在这种情况下会有所帮助。在网络上搜索“StructLayoutAttribute”;你会找到教程。

  • 长,双或弦,真的吗?不能是 int、float 或 string?数据是否真的超过了数十亿的数量级或精确到小数点后 15 位?对于 99% 的情况,int 和 float 不能完成这项工作吗?它们只有一半大小。

通常我不建议使用 float over double,因为它是一种虚假的经济;当他们有一个数字时,人们通常会以这种方式节约,就像节省四个字节会有所作为。4200 万个浮点数和 4200 万个双精度数之间的差异是相当大的。

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

  • 将布尔值存储为字节中的位;编写属性来进行位移以将它们取出。以这种方式为自己节省几个字节。

  • 请记住,内存实际上是磁盘空间;RAM 只是它上面的一个方便的缓存。如果数据集太大而无法保存在 RAM 中,那么某些东西会将其分页回磁盘并稍后再读回;那可能是您,也可能是操作系统。您可能比操作系统更了解您的数据位置。您可以以某种方便的可分页形式(如 b 树)将数据写入磁盘,并且更有效地将数据保存在磁盘上,并且仅在需要时才将其放入内存。

于 2011-01-29T16:51:53.307 回答
14

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

当然,你不会保存任何东西。“动态”只是戴着花哨的帽子的“对象”。“动态”对象仍被装箱。

于 2011-01-27T23:44:18.017 回答
3

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

此外,所有这些努力真的值得每个对象 12 个字节吗?与节省几千字节(如果有的话)RAM 相比,您的时间肯定有更好的用途吗?您是否证明您的程序使用 RAM 实际上是一个问题?

于 2011-01-27T23:39:13.387 回答
2

不会。Dynamic 只会将其存储为对象。

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

于 2011-01-27T23:38:04.127 回答