c# - 这是否适合类或结构(速度比内存更重要)?

标签 c# .net class struct

通常,我永远不必问自己给定的场景是否更适合结构或类,坦率地说,在这种情况下,在采用类方式之前我没有问过这个问题。现在我正在优化,事情变得有点困惑。

我正在编写一个数字处理应用程序,用于处理包含数百万 Base10 数字的极大数字。数字是二维空间中的 (x,y) 坐标。主要算法是非常连续的,并且在任何给定时间内存中的类 Cell(如下所列)的实例不超过 200 个。该类的每个实例占用大约 5MB 的内存,导致应用程序的总峰值内存不超过 1GB。最终产品将在具有 20GB RAM 的 16 核机器上运行,并且没有其他应用程序占用资源。

这是类:

// 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 的实例,它本身是一个结构,因此考虑临时赋值调用会有多少开销。

问题是,考虑到速度效率是这种情况下的最终目标,我在这里的选择是否明智?

以下是有关该算法的一些信息,希望对您有所帮助。在每次迭代中:

  1. 对所有 200 个实例执行一次排序。 20% 的执行时间。
  2. 计算感兴趣的相邻 (x,y) 坐标。 60% 的执行时间。
  3. 上面第 2 点的并行/线程开销。 10% 的执行时间。
  4. 分支开销。 10% 的执行时间。
  5. 最昂贵的函数:BigInteger.ToByteArray() (implementation) .

最佳答案

这会更适合作为一个类,原因有很多,包括

  • 它在逻辑上不表示单个值
  • 大于16字节
  • 它是可变的

有关详细信息,请参阅 Choosing Between Classes and Structures .

此外,我还建议它更适合给定的类:

  • 它包含引用类型(数组)。包含类的结构很少是一个好的设计理念。

不过,考虑到您正在做的事情,这尤其正确。如果您要使用 struct ,排序将需要整个结构的副本,而不仅仅是引用的副本。方法调用(除非由 ref 传递)也会产生巨大的开销,因为您将复制所有数据。

集合中项目的并行化也可能会产生巨大的开销,因为对结构的任何数组进行边界检查(即:如果它保存在 List<Cell> 或类似的数组中)会导致错误的错误共享,因为所有对该列表将访问列表开头的内存。

我建议将其保留为一个类,此外,我建议尝试将字段移动到属性中,并尽可能使该类不可变。这将有助于保持您的设计简洁,并且在多线程时不太可能出现问题。

关于c# - 这是否适合类或结构(速度比内存更重要)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12117433/

相关文章:

c# - 数学舍入问题总计 > 100%

c# - PropertyGrid - 根据另一个属性值更改下拉属性编辑器的项目

arrays - 无法使用 Swift 在 Xcode 中的类中创建数组

.net - 如何捕获 'n. def' 异常(例如 : Sqrt of negative double number)

c# - XmlDocument读取XML文档注释问题

Python从类列表中选择项目

Ruby 类方法命名冲突

c# - WPF 将 RichTextBox 打印为图像

c# - JSON 解析错误 - 位置 0 处的字符无效

c# - 如何创建从 FrameworkElement 派生的自定义复合控件