2012-06-21 10 views
5

私はパフォーマンスやメモリ使用量を改善することを検討していませんが、この質問は純粋に好奇心から始まりました。 C#コンパイラは、(モノ+ .NET)4バイトに2つのshort変数をパックするか、彼らは(アライメントで)8つのバイトを消費します次のクラスを考えると小さなデータ型はどのようにC#でパックされます

主な質問

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; } 
    } 
} 
+3

C#コンパイラはこれと関係がありません。ランタイムになります。 –

+0

「非常に大量に使用されています」と言えば、何回話していますか?どのように使用されていますか?これらの配列/リスト/ etcを作っていますか? –

+0

@ReedCopseyはい、このコンテキストの理論は、インデックスによる特定のエントリへの頻繁なアクセスを伴う大きなリストになります。 –

答えて

5

チェックしてください。 [StructLayout]でデフォルトの動作を上書きすることができますが、デフォルト動作は問題ありません。

合計サイズを最小限に抑えることが絶対条件であれば、classの代わりにstructと考えることができます。クラスを使用する場合、クラスの各インスタンスは大きなオーバーヘッドを追加します。 syncblk、TypeHandleなどと、64ビットシステム上の別の8バイトの参照)との間では、オブジェクトインスタンスは2つの短絡の上および上のかなりの量の "余分な"メモリを使用します。詳細は、"How the CLR Creates Runtime Objects"を参照してください。

データを値型のコレクションにパックして格納すると、これを完全に回避できます。また、インスタンスの合計を合計8バイト(コレクションのオーバーヘッド)に抑えることもできます。これはセマンティクスを変更していますが、2つのshortを使用している場合、特に64ビットシステムでは、タイプに関係するオーバーヘッドが減少します。

+0

ありがとうございました。ここにはいくつかの素晴らしい回答があります。リンクありがとう、私は読んでいるでしょう! –

6

それは、 @David_Mのようにランタイムに依存しますが、[StructLayout]属性を使用して強制することができます。この属性には、梱包を制御するために使用できるPackのメンバーがあります。あるいは、[FieldOffset]を使用して、構造体のメンバーを手動でレイアウトすることもできます(オーバーラップ、.NETでのユニオンの実装方法)。

2

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

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

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

詳細情報についてはこれは実行時ではなく、コンパイラに依存MSDN- Structlayout

関連する問題