この質問は主に、ここにある私の以前の投稿に基づいています。
リフレクションを使用して SOS.dll の機能の一部を再作成しようとしています。具体的にはコマンドObjSize
とDumpObject
コマンド。リフレクションを使用してすべてのフィールドを検索し、フィールドがプリミティブ型の場合は、プリミティブ型のサイズをオブジェクト全体のサイズに追加します。フィールドが値型の場合は、元のメソッドを再帰的に呼び出し、すべてのプリミティブ型フィールドに到達するまで参照ツリーをたどります。
オブジェクト サイズが常に SOS.dll ObjSize コマンドよりも 2 倍ほど大きくなっています。私が見つけた理由の 1 つは、リフレクション コードが、SOS が無視しているフィールドを見つけているように見えることです。たとえば、ディクショナリでは、SOS は次のフィールドを検索します。
- バケツ
- エントリ
- カウント
- バージョン
- フリーリスト
- freeCount
- 比較者
- キー
- 値
- _syncRoot
- m_siInfo
ただし、私のリフレクション コードは上記のすべてを検出し、以下も検出します。
- バージョン名
- ハッシュサイズ名
- KeyValuePairsName
- 比較者名
また、SOS の ObjSize コマンドと DumpObject コマンドで見つかった矛盾についても混乱しています。DumpObject が参照される型のサイズを調べていないことはわかっています。ただし、上記の辞書で Object size を呼び出すと、次のようになります。
- 辞書 - 532B
次に、Dictionary で DumpObject を呼び出して、その参照型のメモリ アドレスを取得します。次に、参照型で Objsize を呼び出すと、次のようになります。
- バケット - 40
- エントリ - 364
- 比較 - 12
- キー - 492
- (残りは null またはプリミティブ)
最上位のディクショナリの ObjSize は、ディクショナリ内のフィールドのすべての ObjSizes のおおよその合計であるべきではありませんか? Reflection が DumpObject よりも多くのフィールドを検出するのはなぜですか? リフレクション分析で SOS.dll よりも大きな数値が返される理由について何か考えはありますか?
また、上記のリンク先のスレッドで尋ねられた質問の 1 つに対する回答も得られませんでした。オブジェクトのメモリ サイズを評価するときに、プロパティを無視する必要があるかどうかを尋ねていました。一般的なコンセンサスは、それらを無視することでした。ただし、プロパティのバッキング フィールドが Type.GetFields() から返されるコレクションに含まれない場合の良い例を見つけました。String のフードの下を見ると、次のようになります。
オブジェクトには、FirstChar という名前のプロパティが含まれています Chars という名前のプロパティが含まれています オブジェクトには、m_stringLength という名前のフィールドが含まれています オブジェクトには、m_firstChar という名前のフィールドが含まれています Empty オブジェクトには、TrimHead という名前のフィールドが含まれていますオブジェクトには alignConst という名前のフィールドが含まれます。m_firstChar
とはプロパティのm_stringLength
バッキング フィールドですが、文字列の実際の内容は Chars プロパティに保持されます。これは、文字列内のすべての文字を返すようにインデックス付けできるインデックス付きプロパティですが、文字列の文字を保持する対応するフィールドが見つかりません。FirstChar
Length
その理由について何か考えはありますか?または、インデックス付きプロパティのバッキング フィールドを取得する方法は? インデックス付きプロパティをメモリ サイズに含める必要がありますか?