5

私はパフォーマンスやメモリ使用量を改善するつもりはありません。この質問は純粋に好奇心から生まれました。

主な質問 次のクラスが与えられた場合、C#コンパイラ(Mono + .NET)は2つのshort変数を4バイトにパックしますか、それとも8バイトを消費しますか(アライメントあり)?

public class SomeClass {
    short a;
    short b;
}

二次質問 上記の質問に対する答えが4バイトではなかった場合、次の代替案は何らかの利点を提供しますか(SomeClass非常に大量に使用される場合)。

// Warning, my bit math might not be entirely accurate!
public class SomeClass {
    private int _ab;

    public short a {
        get { return _ab & 0x00ff; }
        set { _ab |= value & 0x00ff;
    }
    public short b {
        get { return _ab >> 8; }
        set { _ab |= value << 8; }
    }
}
4

3 に答える 3

6

@David_Mが言うように、ランタイムによって異なりますが、パッキングを制御するために使用できるメンバーを[StructLayout]持つ属性を使用して、強制的に実行できます。または、を使用して構造体のメンバーを手動でレイアウトするPackこともできます(オーバーラップすることもできます。これは、.NETでユニオンを実装する方法です)。[FieldOffset]

于 2012-06-21T15:01:00.463 に答える
5

これは、コンパイラではなく、ランタイムに依存します。デフォルトの動作をでオーバーライドできます[StructLayout]。これは役立つ場合がありますが、デフォルトの動作は問題ないはずです。

そうは言っても、合計サイズを最小化することが絶対的な要件である場合は、のstruct代わりに検討することをお勧めしますclass。クラスを使用する場合、クラスの各インスタンスはかなりのオーバーヘッドを追加します。syncblk、TypeHandleなど、および参照(64ビットシステムではさらに8バイト)の間で、オブジェクトインスタンスは2つのショートを超えてかなりの量の「余分な」メモリを使用します。詳細については、「CLRがランタイムオブジェクトを作成する方法」を参照してください。

値型のコレクションにパックされたデータを格納すると、これを完全に回避でき、インスタンスをそれぞれ合計8バイト(およびコレクションのオーバーヘッド)に抑えることができます。当然のことながら、これにより使用法のセマンティクスが変更されますが、2つのショートのみを使用している場合は、特に64ビットシステムで、タイプに関連するオーバーヘッドの量が削減されます。

于 2012-06-21T15:03:25.190 に答える
2

他の人がコメントしているように、実際のレイアウトはランタイムによって異なります。これは主に、複数のプラットフォームで同じコードを実行できるためです。

そして、スペースを節約する多くのオブジェクトの場合はそうです。探しているのはLayoutKind(StructLayout属性)です。それはあなたが好きなようにメンバーを詰めることができます。たとえば、Sequentialを使用すると、しっかりと梱包されていることを確認できます。

[StructLayout(LayoutKind.Sequential)]
public class SomeClass {
    short a;
    short b;
}

詳細については、MSDN-Structlayoutを確認してください。

于 2012-06-21T15:01:10.190 に答える