通常,我永远不必问自己给定的场景是否更适合结构或类,坦率地说,在这种情况下,我在上课之前没有问过这个问题。现在我正在优化,事情变得有点混乱。
我正在编写一个数字处理应用程序,该应用程序处理包含数百万个 Base10 数字的极大数字。这些数字是 2D 空间中的 (x,y) 坐标。Cell
主要算法是非常连续的,并且在任何给定时间,内存中的类实例(如下所列)不超过 200 个。该类的每个实例占用大约 5MB 的内存,导致应用程序的总峰值内存不超过 1GB。成品将在 16 核机器上运行,具有 20GB 的 RAM,并且没有其他应用程序占用资源。
这是课程:
// Inheritance is convenient but not absolutely necessary here.
public sealed class Cell: CellBase
{
// Will contain numbers with millions of digits (512KB on average).
public System.Numerics.BigInteger X = 0;
// Will contain numbers with millions of digits (512KB on average).
public System.Numerics.BigInteger Y = 0;
public double XLogD = 0D;
// Size of the array is roughly Base2Log(this.X).
public byte [] XBytes = null;
public double YLogD = 0D;
// Size of the array is roughly Base2Log(this.Y).
public byte [] YBytes = null;
// Tons of other properties for scientific calculations on X and Y.
// NOTE: 90% of the other fields and properties are structs (similar to BigInteger).
public Cell (System.Numerics.BigInteger x, System.Numerics.BigInteger y)
{
this.X = x;
this.XLogD = System.Numerics.BigInteger.Log(x, 2);
this.XBytes = x.ToByteArray();
this.Y = y;
this.YLogD = System.Numerics.BigInteger.Log(y, 2);
this.YBytes = y.ToByteArray();
}
}
我选择使用类而不是结构只是因为它“感觉”更自然。字段、方法和内存的数量都本能地指向类而不是结构。我进一步证明,通过考虑临时分配调用会有多少开销,因为底层的主对象是 BigInteger 的实例,它本身就是一个结构。
问题是,考虑到速度效率是这种情况下的最终目标,我是否明智地选择了这里?
这里有一些关于算法的信息,以防万一。在每次迭代中:
- 对所有 200 个实例执行一次排序。20% 的执行时间。
- 计算感兴趣的相邻 (x,y) 坐标。60% 的执行时间。
- 上述第 2 点的并行/线程开销。10% 的执行时间。
- 分支开销。10% 的执行时间。
- 最昂贵的函数:BigInteger.ToByteArray() (实现)。