Comments 16
В Ignite.NET использование stackalloc
для передачи JNI аргументов (varargs
/ va_list
) вместо params JavaValue[]
подняло перформанс реальных кэшовых операций на 15% и избавило от лишних аллокаций / GC.
Код на гитхабе: UnmanagedUtils.cs
Ещё пример, перетасовка байт: WriteGuidSlow
Думаю, что stackalloc
используется так редко, потому что либо размер буфера предопределён и данные структурированы, тогда просто заполняется struct
и берётся указатель, либо размер буфера непредсказуем.
необходимо тщательно проверять работу тех методов, в которые уходит ссылкаО, за решётку в буханке протянули двуствольный ногострел!
(void *) т.к.
int* buff = stackalloc int[Random.Next(100500)];
if (buff == null) RainbowFire();
Хочу отдельно отметить, что стиль изложения в этой части лучше. Текст гораздо легче читается.
Плюс есть еще отдельные личности, которые ведут видеоблоги. Как, например, Immo Landwerth из команды ядра
Тут, в вашей статье Менеджмент памяти в .Net Framework от Redgate, нашлась ещё пара ссылок.
Иногда (например в этом докладе) stackalloc
не рекомендуют использовать, говоря, что он заполняет выделенную память нулями, и из-за этого работает медленно. На гитхабе coreclr эта тема тоже обсуждалась, и там есть пример, когда stackalloc
не заполняет память нулями (я немного модифицировал этот пример):
const int Size = 16384;
static unsafe void Main() {
Foo();
byte* p = stackalloc byte[Size];
Console.WriteLine(p[0]);
}
static unsafe void Foo() {
byte* p = stackalloc byte[Size];
for (int i = 0; i < Size; i++)
p[i] = 42;
}
Если в этом коде менять Size на разные значения — можно получить разный результат. На моей машине с .NET Framework 4.7.1 результаты такие:
RyuJit x64:
- Size: 1-48, значение: 0
- Size: 49-64 — «случайное» число,
- Size >=65 — 42
LegacyJit x86:
- Size 1-24 — 0
- Size >=25 — 42
При этом в машинном коде Foo
заполнение нулями присутствует.
Отсюда появляются вопросы — в каких случаях при использовании stackalloc
память обнуляется, как это влияет на производительность, и зачем вообще нужно обнуление, если на него нельзя полагаться?
Сейчас в coreclr память не обнуляется для любых размеров буфера. Это было сделано для эффективного использования Span в случае когда нужна производительность.
https://github.com/dotnet/coreclr/pull/13728
https://github.com/dotnet/coreclr/issues/1279
[DotNetBook] Stackalloc: забытая команда C#