[英]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.