UnsafeList builds its growth factor into the SetCapacity function meaning there’s no way to set an exact length for the underlying buffer. Here’s the relevant snippet from the source:
void SetCapacity<U>(ref U allocator, int capacity)
{
// ...
var newCapacity = math.max(capacity, CollectionHelper.CacheLineSize / sizeOf);
newCapacity = math.ceilpow2(newCapacity);
// ...
}
If I know the upper bound of a list’s length I’d like to allocate only that amount (or close enough to that amount) of memory. I get that this probably doesn’t matter when the allocation is backed by virtual memory and you don’t actually touch the excess capacity. However, it doesn’t work well with custom allocators like stack or bump allocators with a fixed upper bound on the memory they can use.
Here’s some cases I’ve run into where this can leave gaps in memory:
- Allocating anything just slightly over a power of two, for example a heightmap array where the map has 2048^2 cells I allocate (2048+1)^2 vertices. This leaves nearly 50% of the allocated memory unused. One workaround here is to TrimExcess() at the cost of a second allocation and copy.
- The initial capacity in the constructor obeys the same logic. This makes it difficult to use with custom allocation strategies like a bump allocator where the TrimExcess() workaround doesn’t work.