3

文字列の大きな行列を の大きな行列に変換するコードがありますMyClassMyClass私が書いた小さなクラスで、各文字列に関する情報を格納し、次のようになります。

class MyClass
{
    public MyEnum Class { get; private set; }

    public int A { get; private set; }
    public int B { get; private set; }
    public int C { get; private set; }
    public int D { get; private set; }
}

現在、このソフトウェアは 5 ~ 20 列× 100 万行の行列を処理できますが、行数を 1000 万近くまで増やしたいと考えています。文字列行列のフットプリントを減らすためにできることはあまりないと思いますが、のメモリフットプリントを減らしたいと思いMyClassます。

short列の型として、および、Aおよびの型として使用できますが、これにはコードの大規模なリファクタリングが必要になります。byteBCD

私の質問、またはむしろ質問:

  1. 使用するコードをリファクタリングする価値はshortありbyteますか?
  2. MyEnumタイプになるようにリファクタリングする必要がありbyteますか?
  3. クラスをより効率的にするために他にできることはありますか?

お時間をいただきありがとうございました!

編集: もう少しコンテキスト - の行列はMyClass、分析のために文字列の行列から作成されます。文字列のマトリックスは平凡なネットワーク接続を介してテキスト ファイルから引き出されるため、タスクを小さなチャンクに分割することは理想的ではありません。

4

5 に答える 5

2

もちろん、文字列に含まれる内容に応じて、文字列行列のサイズを縮小するためにできることはたくさんあります。重複した文字列が多数ある場合は、文字列インターンを使用するか、文字列プールを構築できます。

文字列が重複しておらず、通常は ASCII またはその他のシングルバイト エンコーディング (または大多数のシングルバイト文字を含む UTF-8) である場合は、文字列リソース テーブルを構築することで多くのメモリを節約できます。概要については、ストリングに必要なメモリーの削減を参照してください。

の場合、MyClassインスタンスごとに 16 バイトの割り当てオーバーヘッドが発生します。これは、データ自体が占めるのとほぼ同じです。structメンバーがすべて不変の場合は、 にすることをお勧めします。それらは公的に不変であるように見えます。あなたが個人的に何をしているか、私にはわかりません。しかし、このようなもの:

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct MyStruct
{
    public readonly MyEnum Class;
    public readonly int A;
    public readonly int B;
    public readonly int C;
    public readonly int D;

    public MyStruct(MyEnum cls, int a, int b, int c, int d)
    {
        Class = cls;
        A = a;
        B = b;
        C = c;
        D = d;
    }
}

インスタンスごとの割り当てオーバーヘッドなしで、インスタンスごとに合計 20 バイトになります。したがって、1,000 万行 x 20 列は (10M * 20 * 20)、つまり約 4 ギガバイトになります。.NET 4.5 では、gcAllowVeryLargeObjects構成設定を使用して、そのサイズの配列を作成できます。

ただし、パフォーマンスの問題が発生する可能性があることに注意してください。次のコードを検討してください。

MyStruct m = MyArray[x,y];
// now access fields of m

構造体を使用すると、アイテムのコピーMyArray[x,y]が に作成されます。これは、20 バイトをコピーすることを意味します。m.Aまた、 を変更しても、その変更は配列に反映されないことも意味します。それをコピーして戻す(つまりMyArray[x,y] = m;)か、中間変数を完全に放棄して次のように書く必要がありますMyArray[x,y].A = 5;

もちろん、構造が不変であれば、コピーバックの問題はありません。

C# を使用してメモリ内の多数の項目を操作することは可能ですが、その方法については工夫が必要です。このように構造体を使用すると、特に構造体が不変の場合に非常に効果的であることがわかりました。

于 2013-08-06T18:01:54.507 に答える
0

クラスを小さくするという点では、他のデータ型を使用するというあなたの主張は正しいです。これにより、割り当てられたメモリ量全体が減少します。メモリ内のデータ表示に関しては、ある種の花を作成しているようですね。この場合、主にコレクションへの参照と呼ばれる他の最適化があります。つまり、各列内に実際の値を格納していません。一意のエントリを持つ辞書に属する他の値への参照を格納しています。さらに、別の方法でデータを調整する必要があります。行指向ではなく、メモリ内 (または少なくとも脳内) で列指向のデータ表示に切り替えます。

これらは、大量のデータを hd ではなくメモリに保持するために SAP hana で使用される手法です。

于 2013-08-06T16:02:05.710 に答える
0

MyClassクラスを使用する場合、 の各値に対して 1 つのn サブクラスを作成しMyEnum(これMyEnumは に離散量の値がある場合)、次に を削除することによってゲインを得ることができますMyEnum

これMyClassは、明らかにクラスである場合にのみ機能します。

于 2013-08-06T17:10:10.490 に答える