通常、特定のシナリオが構造体またはクラスに適しているかどうかを自問する必要はありません。率直に言って、この場合、クラスの方法に進む前にその質問をしませんでした。最適化を行っている今、状況は少し混乱しています。
何百万もの Base10 桁を含む非常に大きな数を処理する数値処理アプリケーションを作成しています。数値は 2D 空間の (x,y) 座標です。Cell
メイン アルゴリズムはかなりシーケンシャルであり、任意の時点でメモリ内にあるクラス (以下にリスト) のインスタンスは 200以下です。クラスの各インスタンスは約 5MB のメモリを占有するため、アプリケーションの合計ピーク メモリは 1GB を超えません。完成した製品は、20 GB の 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 のインスタンスであるため、一時的な代入呼び出しのオーバーヘッドがどの程度になるかを考慮して、それを正当化しました。
問題は、速度効率がこの場合の最終目標であることを考慮して、ここで賢明に選択したかどうかです。
役立つ場合に備えて、アルゴリズムについて少し説明します。各反復で:
- ソートは 200 個のインスタンスすべてに対して 1 回実行されました。実行時間の 20%。
- 対象の隣接 (x,y) 座標を計算します。実行時間の 60%。
- 上記のポイント 2 の並列/スレッド化のオーバーヘッド。実行時間の 10%。
- 分岐オーバーヘッド。実行時間の 10%。
- 最も高価な関数: BigInteger.ToByteArray() (実装)。