-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Description
Currently, when a type like List<T> wants to resize an array, it has to allocate a new array and copy all the elements from the old array to the new one (possibly using Array.Resize()). I think this copying can take a fairly long time, especially for large arrays.
But considering that on 64-bit platforms, there should be enough free virtual address space, would it be possible to "reserve" more address space for such growing arrays, so that they can be grown in place?
The way I imagine it could work is something like this:
- There would be a new type
ResizableArray<T>*, which would mostly behave just like an array, except that itsLengthcan change and that itsResizemethod (public static void Resize(ref ResizableArray<T> array, int minNewSize)) either allocates a newResizableArray<T>or changes itsLength(see below). It has to be a new type, because nobody expects that theLengthofT[]can change. - If
ResizableArray<T>.Resizewas called with a smallminNewSize, it would behave similarly toArray.Resizeand reallocate. - If called with a sufficiently large
minNewSizeon a smallResizableArray<T>(the limit could be the same as for LOH, or larger, depending on how fast reallocating an array is and how much wasting of virtual address space is acceptable), the array would be reallocated into a special area of memory, reserving its maximum size for it (AFAIK 232 · element size) in the virtual address space, but actually allocating only as much physical memory as requested. This would make it a "large"ResizableArray<T>. - If called on a large
ResizableArray<T>, it would just allocate the new memory, without copying anything, since the virtual address space is available. - If virtual address space ran out because of too many resizable arrays (e.g. more than ~16k resizable
intarrays on architectures with 48-bit address space like x64), part of the reserved address space for some resizable array could be reused. CallingResizeon that array could then potentially reallocate it. - Since
ResizableArray<T>.Resizewould actually allocate physical memory from the OS by pages, it could resize the array to more than what was asked for, which would mean no physical memory would be wasted (that's why the parameter is calledminNewSize). - Just like normal array,
ResizableArray<T>could be converted toSpan<T>, which means there would be a common abstraction.
My questions:
- Would this be possible?
- Could this actually sufficiently increase performance?
- Would the cost of making this work and adding the new type be warranted?
- Are there better ways to solve this issue?
I think creating this type is primarily a matter of implementation, not API, which is why I'm opening this issue here, and not on corefx.
* This name is very similar to ResizeArray<T>, which is an F# alias for System.Collections.Generic.List<T>. So maybe a different name would be better?