2011-11-26 79 views
1

我想優化一些代碼,我有大量的數組包含不同大小的結構,但基於相同的接口。在某些情況下,結構體積較大,容納的數據較多,而其他結構體系較小,而其他情況下,我希望保留空值作爲節省內存的值。如何確定C#中的非託管數組的大小?

我的第一個問題是。做這樣的事情是一個好主意嗎?我以前有一個完整的數據結構數組,但是當測試混合它時,我幾乎可以節省大量的內存。還有其他缺點嗎?

我一直在嘗試不同的事情,並且在製作一個通用接口數組時接縫工作得很好,但我不確定是否正確地檢查了數組的大小。

爲了簡化這個例子不少。但是我在這裏給數組添加了不同的結構。但我無法使用傳統的Marshal.SizeOf方法來確定大小。簡單地遍歷集合並計算集合中每個值的sizeof是否正確?

IComparable[] myCollection = new IComparable[1000]; 
myCollection[0] = null; 
myCollection[1] = (int)1; 
myCollection[2] = "helloo world"; 
myCollection[3] = long.MaxValue; 

System.Runtime.InteropServices.Marshal.SizeOf(myCollection); 

最後一行將拋出此異常:

Type 'System.IComparable[]' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed. 

藉口長崗:

  1. 這是一個最佳的和可用的解決方案?
  2. 如何確定我的陣列的大小 ?
+0

我可能是錯的,但它在我看來像你的IComparable []數組是一個託管數組? –

回答

0

最佳性總是取決於您的要求。如果你真的需要存儲不同類/結構的許多元素,你的解決方案是完全可行的。

但是,我想你對數據結構的期望可能會誤導:數組元素是每個定義都是相同的大小。在你的情況下甚至是這樣的:你的數組本身並不存儲元素,但引用(指針)。元素在VM堆的某處分配。所以你的數據結構實際上是這樣的:它是一個1000個指針的數組,每個指針指向一些數據。每個特定元素的大小當然可以變化。

這會導致下一個問題:數組的大小。你打算怎麼處理這個尺寸?當您將數據序列化到某些持久性存儲時,是否需要知道要分配多少個字節?這取決於序列化格式......或者您需要粗略估計一下您的結構消耗了多少內存?在後一種情況下,您需要考慮數組本身以及每個特定元素的大小。您在示例中給出的數組大約消耗參考大小的1000倍(在32位計算機上應爲4個字節,在64位計算機上應爲8個字節)。要計算每個元素的大小,您確實可以遍歷數組並總結特定元素的大小。請注意,這只是一個估計:虛擬機增加了一些內存管理開銷,這是難以確定的確切...

+0

謝謝!這回答了我的問題。我主要想知道數組是如何保存在物理內存中的,因爲我有很多數組,並且試圖用較小的結構替換一些條目。根據你的說法,我可以從數組的大小*參考的內存使用情況+迭代時的數據內存大小來計算。正確? – jsmars

1

我可能是錯的,但它在我看來像你的IComparable []數組是一個託管數組?如果是這樣,那麼你可以使用此代碼來獲取長度

int arrayLength = myCollection.Length; 

如果你正在做的C#和C之間的互操作平臺++再回答你的問題的標題「我能找到一個非託管數組的長度」是否定的,這是不可能的。在C++/C數組函數簽名傾向於遵循以下模式

void doSomeWorkOnArrayUnmanaged(int * myUnmanagedArray, int length) 
{ 
    // Do work ... 
} 

在.NET數組本身是具有一些基本信息,如它的大小,它的運行時類型等類型...因此,我們只要使用平臺調用C#和C之間進行互操作可以使用此

void DoSomeWorkOnManagedArray(int [] myManagedArray) 
{ 
    int length = myManagedArray.Length; 
    // Do work ... 
} 

++你將需要數組的長度傳遞給接收功能,以及引腳陣列(但是這是一個不同的主題)。

這是回答您的問題嗎?如果沒有,那麼請你澄清

+0

感謝您的回答,抱歉,如果問題不清楚。我主要想知道這樣一個數組的內存使用情況。我有大量的數組保存大量數據,所以我試圖用較小的優化結構替換一些條目,並且在某些情況下使用空值來節省物理內存。 – jsmars