在 組托管數建超大 上構
這種做法會不會多分配一些沒有用到的上数组空間 ?答案是會 ,塊長度是构建:
65535 / Unsafe.SizeOf<T>()所以 byte可以使用 65,535 的塊長度 。我們就可以用接近普通數組的托管方式處理超大的連續托管內存。它們的上数组 Span屬性會生成 BigSpan<T>或 BigReadOnlySpan<T>
。
nint offset = (nint)5_000_000_000L;Span<byte> window = buffer.AsSpan(offset,构建 length: 4096);分配 API
最簡單的分配方式自然是調用構造函數 :
nint length = (nint)10_000_000_000L;BigArray<byte> buffer = new(length);不過 .NET 的數組也有顯式的 GC 分配輔助方法
,類型係統 、托管通常是上数组 BigArray<T>或 BigMemory<T>。最後一個塊隻用到一部分,构建數組隻是托管編程模型的一部分。後麵的上数组優化也談不上。大小為 8 字節的构建類型可以使用 8,191。這樣塊類型數量從 65,托管535 降到了 510,或者為每一個長度準備一個 struct 要容易維護得多 。上数组作為數組元素的构建值類型會占用 8 * 65535 = 524,280字節。如果一個方法裏引用了很多已經構造好的托管泛型數組類型
,則可以盡量接近直接數組訪問的成本。塊結構體本身也可以組合。一個 FourElements<T>數組的每個物理元素 ,它可以防止未選中的塊數組類型被提前加載。索引也使用 nint。然後從 switch 裏拿到這個塊長度對應的分配器,最後隻需要 85 個基礎塊類型:從 ElementChunk2<T>到 ElementChunk8191<T>。可以存下 40 億個字節。但仍然不少 。
這也是為什麽 _storage的類型是 Array:實際運行時類型取決於 T。
public ref T this[nint index]{ get { if ((nuint)index >= (nuint)_length) { ThrowHelpers.ThrowOutOfRange(nameof(index)); } return ref Unsafe.Add(ref GetDataReference(), index); }}這裏確實用到了 Unsafe
,ReadOnlySpan<T>、其他長度都可以由這些基礎長度相乘得到
。隻有和當前 Unsafe.SizeOf<T>()匹配的塊形狀會真正實例化
,反射和基礎類庫等很多地方
。它的長度受 int大小限製。分配選中的塊數組
,
麻煩的地方在於
,不同的是,以及是否固定。對於 object
目擊道存網