一直有一個小小的疑惑——NET一個對象或者一個集合占多少內存?有沒有很快速的方法獲取而不是簡單的估計分析對象大小?
查了MSDN和一些其他人的分析得到解決是托管代碼對象的大小無法真實的得到因為存在托管對象轉化成非托管的CLR優化但我仍然不死心非要弄個究竟!好吧最終得到一些結果了
sizeof關鍵字用於獲取值類型的大小如int(占個字節)char(個字節);並且sizeof 運算符僅適用於值類型而不適用於引用類型所以針對對象改關鍵字無法使用
查閱msdn發現對象MarshalSizeOf 方法解釋為返回類的非托管大小;但是仍然不能使用因為針對的是非托管代碼如果直接使用一個類的對象會報一個錯誤不能作為非托管結構進行封送處理;無法計算有意義的大小或偏移量;這是因為對象在內存中實際大小並不是固定的可能這次運行一個值下次就是另外一個值了存在優化!
所以為了固定一個對象的大小必須告訴CLR不優化對象在內存中的大小這就需要在聲明類的時候加上[StructLayout(LayoutKindSequential)]這個特性;
StructLayoutAttribute 類使用戶可以控制類或結構的數據字段的物理布局
LayoutKind 枚舉 控制當導出到非托管代碼時對象的布局
成員名稱 |
說明 |
Sequential
對象的成員按照它們在被導出到非托管內存時出現的順序依次布局
這些成員根據在 StructLayoutAttribute
::
Pack 中指定的封裝進行布局
並且可以是不連續的
Explicit
對象的各個成員在非托管內存中的精確位置被顯式控制
每個成員必須使用 FieldOffsetAttribute 指示該字段在類型中的位置
Auto
運行庫自動為非托管內存中的對象的成員選擇適當的布局
使用此枚舉成員定義的對象不能在托管代碼的外部公開
嘗試這樣做將引發異常
這就是控制對象轉化為非托管代碼時占用內存固定這樣我們就可以舒服的使用MarshalSizeOf方法了得到一個對象的大小如果一個對象中還包含另外一個對象那麼另外一個對象可以使用這個[StructLayout(LayoutKindSequential)]也可以不使用如果使用則是該對象的大小加上這個對象的大小;如果不使用則是該對象的大小加上個字節(就是這個對象引用大小)
當想獲取一個集合的大小時候我們不能在List上加這個屬性因為微軟的dll中的類那麼我們怎麼樣才能獲取對應的大小呢?其實還用一種簡單的方式就是將對象或者集合轉化成內存流再獲取內存流的大小就ok了雖然有一些其他影響大小但基本上可以正確的粗略估計一個對象在內存的大小或者比較倆個對象集合的大小的!
主要代碼
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
binaryFormatterSerialize(stream personList);
streamSeek( SeekOriginBegin);
其實裡面東西多著的我僅僅了解了一點點分享一下大家一起討論一下如果有錯誤請批評指出!
From:http://tw.wingwit.com/Article/program/net/201311/13940.html