我有一个控制台应用程序,允许用户指定变量来处理。这些变量有三种口味:弦,双重和长(双重和长期是最常用的类型)。用户可以按照任何顺序指定他们喜欢的任何变量,因此我的系统必须能够处理。为此,在我的应用程序中,我一直将它们存储为对象,然后根据需要铸造/取消它们。例如:

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

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

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

编辑

为了提供一些上下文,并防止“您确定自己使用足够的RAM来担心这一点”,在我最坏的情况下,我有420,000,000个数据点可担心(60个变量 * 7,000,000个记录)。这是我保留每个变量(包括一些布尔等)的其他数据的补充。因此,减少记忆的确会产生巨大影响。

有帮助吗?

解决方案

好,所以 真实的 问题是“我有一个怪异的数据集,我在内存中存储,如何在时间和内存空间中优化其性能?”

几个想法:

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

动态不是吗它是拳击,还有很多其他开销。 (C#的动态非常快 与其他动态调度系统相比, ,但从绝对角度来看,它不是快速或小)。

它是总的,但是您可以考虑使用一个结构,其布局在各个字段之间共享内存 - 就像Con中的一个C.这样做是 真的很粗糙完全不安全 但这可以在这种情况下有所帮助。进行网络搜索“ structlayOutAttribute”;您会发现教程。

  • 长,双重还是字符串,真的吗?不能是int,float或string?数据实际上是超过数十亿的数量级,要么准确地到15个小数位? INT和Float不会为99%的案件完成这项工作吗?它们是一半的大小。

通常,我不建议将Float超过两倍,因为它是虚假的经济;人们经常有一个数字时会节省这种方式,例如四个字节的节省将有所作为。 4200万浮子和4200万双双打之间的差异很大。

  • 数据中是否有规律性可以利用?例如,假设您的4200万条记录中只有100000个实际值,例如,每个double的100000个值,每个字符串的值为100000个值。在这种情况下,您为较长,双打和字符串的某种形式的索引存储,然后每个记录都会获得一个整数,而低位是索引的,顶部的两个位表示哪个存储空间可以将其脱离。现在,您有4200万个记录,每个记录都包含一个INT,并且值以某种精美的紧凑形式存储在其他地方。

  • 将布尔人作为钻头存放在字节中;编写属性以进行钻头转移以使他们脱颖而出。这样可以节省几个字节。

  • 请记住,内存实际上是磁盘空间; RAM在其顶部只是一个方便的缓存。如果数据集太大而无法保存在RAM中,则 某物 要回到磁盘并将其重新阅读后,请稍后再阅读;那可能是您,也可能是操作系统。与操作系统相比,您可能对数据局部性了解更多。您可以以方便的打印形式(例如B-Tree)将数据写入磁盘,并更有效地将其保存在磁盘上,并且只能在需要时将其带入内存。

其他提示

我认为您可能在这里看错误的事情。记住动态的作用。它 在运行时再次启动编译器. 。它为编译器加载数十万个字节代码,然后在每个呼叫站点中都发出的缓存,其中包含新鲜发射的IL的结果,用于每个动态操作。您要花费数十万个字节来节省八个字节。这似乎是个坏主意。

当然,您什么都不保存。 “动态”只是带有花哨的帽子的“对象”。 “动态”对象仍然被装箱。

不。 dynamic 跟。。有关的 如何执行对象的操作, ,不是对象本身存储的方式。在这种特定情况下,价值类型仍将被装箱。

另外,所有这些努力真的价值每个物体12个字节吗?当然,您的时间比节省了几千字节(如果那个RAM)更好吗?您是否证明您的程序使用RAM实际上是一个问题?

否。动态将仅将其作为对象存储。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top