[英]Can you use List<List<struct>> to get around the 2gb object limit?
我正在運行c#中的2gb對象限制(由於某些令人討厭的原因,這甚至適用於64位),其中包含大量結構(總共大小為4.2 gig)。
現在顯然使用List會給我一個大小為4.2gb給定或接受的列表,但是會使用由較小列表組成的列表,而這些列表又包含一部分結構,允許我跳過這個限制嗎?
我的理由是,它只是CLR中的硬編碼限制,阻止我在64位平台上實例化一個9gig對象,而且它與系統資源完全無關。 Lists和Arrays也是引用類型,因此包含列表的List實際上只包含對每個列表的引用。 因此,沒有任何一個物體超過尺寸限制。
有什么理由不行嗎? 我現在自己嘗試一下,但我手邊沒有內存分析器來驗證。
現在顯然使用List會給我一個大小為4.2gb給定或接受的列表,但是會使用由較小列表組成的列表,而這些列表又包含一部分結構,允許我跳過這個限制嗎?
是的 - 但是,如果您正在嘗試解決此限制,我會考慮自己使用數組,而不是讓List<T>
類管理數組。
CLR中的2gb單個對象限制正好是單個對象實例。 當你創建一個struct的數組( List<T>
內部使用)時,整個數組是CLR中的“一個對象實例”。 但是,通過使用List<List<T>>
或鋸齒狀數組,每個內部列表/數組都是一個單獨的對象,它允許您有效地擁有所需的任何大小的對象。
CLR團隊實際上在博客上寫了這個,並提供了一個示例BigArray<T>
實現,其作用類似於單個List<T>
,但在內部為您執行“阻止”管理。 這是獲得> 2gb列表的另一種選擇。
List
包含4或8個字節的引用,具體取決於您是在32位還是64位模式下運行,因此如果您引用的2GB對象不會將實際的List
大小增加到2 GB,但它只會通過引用該對象所需的字節數來增加它。
這將允許您引用數百萬個對象,每個對象可以是2GB。 如果你有在4名對象List
,且各自為2 GB,那么你將有8 GB值得引用對象的List
,但List
對象將只使用一個額外的4×8 = 32個字節。
在List
達到2GB限制之前,您可以在32位計算機上保留的引用數為536.87百萬,而在64位計算機上則為268.43百萬。
5.36億個參考* 2 GB =很多數據!
PS Reed指出,上述內容適用於引用類型,但不適用於值類型。 因此,如果您持有值類型,那么您的解決方法是有效的。 有關詳細信息,請參閱下面的評論。
在4.5之前的.NET版本中,最大對象大小為2GB。 從4.5開始,如果啟用了gcAllowVeryLargeObjects,則可以分配更大的對象。 請注意, string
的限制不受影響,但“數組”也應該涵蓋“列表”,因為列表由數組支持。
class HugeList<T>
{
private const int PAGE_SIZE = 102400;
private const int ALLOC_STEP = 1024;
private T[][] _rowIndexes;
private int _currentPage = -1;
private int _nextItemIndex = PAGE_SIZE;
private int _pageCount = 0;
private int _itemCount = 0;
#region Internals
private void AddPage()
{
if (++_currentPage == _pageCount)
ExtendPages();
_rowIndexes[_currentPage] = new T[PAGE_SIZE];
_nextItemIndex = 0;
}
private void ExtendPages()
{
if (_rowIndexes == null)
{
_rowIndexes = new T[ALLOC_STEP][];
}
else
{
T[][] rowIndexes = new T[_rowIndexes.Length + ALLOC_STEP][];
Array.Copy(_rowIndexes, rowIndexes, _rowIndexes.Length);
_rowIndexes = rowIndexes;
}
_pageCount = _rowIndexes.Length;
}
#endregion Internals
#region Public
public int Count
{
get { return _itemCount; }
}
public void Add(T item)
{
if (_nextItemIndex == PAGE_SIZE)
AddPage();
_itemCount++;
_rowIndexes[_currentPage][_nextItemIndex++] = item;
}
public T this[int index]
{
get { return _rowIndexes[index / PAGE_SIZE][index % PAGE_SIZE]; }
set { _rowIndexes[index / PAGE_SIZE][index % PAGE_SIZE] = value; }
}
#endregion Public
}
這里有一篇關於這個主題的有趣帖子:
http://blogs.msdn.com/b/joshwil/archive/2005/08/10/450202.aspx
其中討論了編寫自己的“BigArray”對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.