C# 你能使用列表吗<;列表<;结构>&燃气轮机;要绕过2gb的对象限制?
我在c#中遇到了2gb的对象限制(由于一些恼人的原因,这甚至适用于64位)和大量的结构集合(估计大小总共为4.2 gig) 现在很明显,使用List会给我一个大小为4.2gb的列表,但使用一个由较小的列表组成的列表,它又包含一部分结构,会允许我跳过这个限制吗 我的理由是,只有CLR中的硬编码限制才能阻止我在64位平台上实例化9gig对象,这与系统资源完全无关。列表和数组也是引用类型,因此包含列表的列表实际上只包含对每个列表的引用。因此,没有任何对象超过大小限制 这有什么原因不起作用吗?我现在想自己试试,但我手头没有内存分析器来验证 现在很明显,使用List会给我一个大小为4.2gb的列表,但使用一个由较小的列表组成的列表,它又包含一部分结构,会允许我跳过这个限制吗C# 你能使用列表吗<;列表<;结构>&燃气轮机;要绕过2gb的对象限制?,c#,memory,memory-management,reference,64-bit,C#,Memory,Memory Management,Reference,64 Bit,我在c#中遇到了2gb的对象限制(由于一些恼人的原因,这甚至适用于64位)和大量的结构集合(估计大小总共为4.2 gig) 现在很明显,使用List会给我一个大小为4.2gb的列表,但使用一个由较小的列表组成的列表,它又包含一部分结构,会允许我跳过这个限制吗 我的理由是,只有CLR中的硬编码限制才能阻止我在64位平台上实例化9gig对象,这与系统资源完全无关。列表和数组也是引用类型,因此包含列表的列表实际上只包含对每个列表的引用。因此,没有任何对象超过大小限制 这有什么原因不起作用吗?我现在想自
是的-但是,如果你想在这个限制范围内工作,我会考虑使用数组,而不是让<代码>列表< /Cord>类管理数组。
CLR中的2gb单对象限制正是单对象实例。当你制作一个结构的数组(它是List
内部使用的)时,整个数组就是CLR中的“一个对象实例”。但是,通过使用列表
或锯齿状数组,每个内部列表/数组都是一个单独的对象,这允许您有效地拥有任意大小的对象
CLR团队实际上在博客上对此进行了讨论,并提供了一个类似于单个列表的实现,但在内部为您执行“阻塞”管理。这是获取>2gb列表的另一个选项
请注意,.NET 4.5将提供选项,但您必须明确选择使用。这里有一篇关于此主题的有趣文章:
关于编写自己的“BigArray”对象。列表
包含4或8字节的引用,具体取决于您是在32位还是64位模式下运行,因此,如果引用的2GB对象不会将实际<代码>列表大小增加到2GB,但只会增加字节数,则有必要引用该对象
这将允许您引用数百万个对象,每个对象可能为2GB。如果列表
中有4个对象,每个对象都是2GB,那么列表
将引用8GB的对象,但列表
对象只会额外使用4*8=32字节
在列表
达到2GB限制之前,在32位机器上可以保存的引用数为5.3687亿,在64位机器上为2.6843亿
5.36亿个引用*2 GB=大量数据强>
p.S.Reed指出,上述情况适用于引用类型,但不适用于值类型。因此,如果您持有值类型,那么您的解决方案是有效的。有关详细信息,请参阅下面的注释。在.NET 4.5之前的版本中,最大对象大小为2GB。从4.5开始,如果启用,则可以分配较大的对象。请注意,
字符串的限制不受影响,但“数组”也应包括“列表”,因为列表由数组支持。类HugeList
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
}
{
私有常量int PAGE_SIZE=102400;
私有const int ALLOC_STEP=1024;
私有T[][]索引;
私有int_currentPage=-1;
私有int_nextItemIndex=页面大小;
私有int_pageCount=0;
私有整数_itemCount=0;
#区域内部
私有void AddPage()
{
如果(++\u currentPage==\u pageCount)
扩展页面();
_rowIndexes[_currentPage]=新的T[页面大小];
_nextItemIndex=0;
}
私有无效扩展页()
{
如果(_rowIndexes==null)
{
_rowIndexes=new T[ALLOC_STEP][];
}
其他的
{
T[][]行索引=新的T[_行索引.Length+ALLOC_步长][];
Copy(_rowIndexes,rowIndexes,_rowIndexes.Length);
_行索引=行索引;
}
_pageCount=_rowIndexes.Length;
}
#端部内部构件
#地区公众
公共整数计数
{
获取{return\u itemCount;}
}
公共作废新增(T项)
{
如果(_nextItemIndex==页面大小)
AddPage();
_itemCount++;
_行索引[\u currentPage][\u nextItemIndex++]=项;
}
公共T此[int索引]
{
获取{return{rowIndexes[index/PAGE_SIZE][index%PAGE_SIZE];}
设置{rowIndexes[索引/页面大小][索引%页面大小]=value;}
}
#终端区公共
}
一个有趣的C#问题有4分钟没有得到回答。我感觉到Jon Skeet正在接近……出于好奇,它需要是一个列表
还是列表
?你可以使用LinkedList
@JamesMichaelHare你可以,但是你会有大量额外的开销,因为每个LinkedListNode
都是一个独立的类,有多个引用。Related@digEmAll如果你的结构足够大,那么它根本不应该是一个结构。。。设计指南说,任何大于16字节的对象都应该是一个类:LinkedListNode
单独有3个引用,而在x64上,仅24字节。。。LinkedList与List的性能语义也完全不同。List与值类型一起使用时,不包含引用(对内部数组的引用除外),但数组本身直接是值类型的数组(T[]
)。一个包含1000个元素的列表,其中MyStruct是1000字节,将使用1000000字节。Th