Proof-of-concept проекта, демонстрирующего создание потока с предаллоцированным стеком 5GB:
- Windows x64 — через
CreateThread - Linux musl (Alpine) — через
mmap + pthread_attr_setstack
Внутри создаётся contiguous регион 4.5GB,
который оборачивается в BigSpan (byte* + ulong Length)
и позволяет получать обычные Span<byte> через .Slice().
/win
Program.cs
stack-poc.csproj
/musl
Program.cs
stack-poc.csproj
Dockerfile
CreateThreadSTACK_SIZE_PARAM_IS_A_RESERVATION- reserve = 5 GiB
- постепенный commit (если нужно)
BigSpan + Slice
- .NET 8.0 SDK или выше
- Windows x64
cd win
dotnet build -c Releasecd win
dotnet run -c Releasemmap(5GB)pthread_attr_setstackpthread_create- arena в нижней части стека
BigSpan + Slice- без stack-grow механизма
- без glibc зависимостей
- Docker
- Минимум 20GB RAM для контейнера (для стека 5GB + OS overhead + .NET runtime)
docker build -t stack-poc ./musl
docker run --rm --memory=20g stack-pocpublic readonly ref struct BigSpan
{
readonly byte* _base;
public readonly ulong Length;
public BigSpan(byte* b, ulong len)
{
_base = b;
Length = len;
}
public ref byte this[ulong index]
{
get
{
if (index >= Length)
throw new IndexOutOfRangeException(
$"Index {index} is out of range. Valid range is 0 to {Length - 1}");
return ref *(_base + (nuint)index);
}
}
public Span<byte> Slice(ulong offset, int length)
{
if (offset > Length)
throw new ArgumentOutOfRangeException(nameof(offset),
$"Offset {offset} exceeds length {Length}");
if ((ulong)length > Length - offset)
throw new ArgumentOutOfRangeException(nameof(length),
$"Length {length} exceeds remaining bytes {Length - offset}");
return new Span<byte>(_base + (nuint)offset, length);
}
}Span<byte>ограниченintSlice()максимум 2GB за раз- Docker memory limit должен быть >5GB
- Windows может требовать достаточный commit limit
Исследование:
- больших стеков (>4GB)
- управления стеком вручную
- обхода guard-grow механизма
- создания custom arena на основе стека
Не предназначено для production.
MIT