簡體   English   中英

你能用List嗎? <List<struct> &gt;繞過2gb對象限制?

[英]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列表的另一種選擇。

請注意,.NET 4.5可以選擇在x64上提供大於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM