Практическое использование ключевого слова stackalloc - PullRequest
110 голосов
/ 24 апреля 2009

Кто-нибудь когда-либо использовал stackalloc при программировании на C #? Я знаю, что делает, но единственный раз, когда он появляется в моем коде, случайно, потому что Intellisense предлагает это, когда я, например, набираю static.

Хотя это не связано со сценариями использования stackalloc, я фактически выполняю значительную часть устаревших взаимодействий в своих приложениях, поэтому время от времени я мог прибегнуть к использованию кода unsafe. Но тем не менее я обычно нахожу способы полностью избежать unsafe.

И поскольку размер стека для одного потока в .Net составляет ~ 1 МБ (поправьте меня, если я ошибаюсь), я еще более зарезервирован от использования stackalloc.

Существуют ли практические случаи, когда можно было бы сказать: «Это именно тот объем данных и обработки, которые мне небезопасны и которые используют stackalloc»?

Ответы [ 4 ]

122 голосов
/ 24 апреля 2009

Единственная причина использования stackalloc - производительность (для вычислений или взаимодействия). Используя stackalloc вместо выделенного массива кучи, вы создаете меньшее давление GC (GC должен работать меньше), вам не нужно закреплять массивы, это быстрее выделить, чем массив кучи, и это происходит автоматически освобождается при выходе из метода (выделенные в куче массивы освобождаются только при запуске GC). Также, используя stackalloc вместо собственного распределителя (например, malloc или эквивалент .Net), вы также получаете скорость и автоматическое освобождение при выходе из области.

С точки зрения производительности, если вы используете stackalloc, вы значительно увеличиваете вероятность попадания кэша в ЦП из-за локальности данных.

35 голосов
/ 24 апреля 2009

Я использовал stackalloc для выделения буферов для работы DSP в реальном времени. Это был очень специфический случай, когда производительность должна была быть максимально последовательной. Обратите внимание, что есть разница между согласованностью и общей пропускной способностью - в этом случае я не был обеспокоен слишком медленным распределением кучи, просто недетерминированностью сборки мусора в этой точке программы. Я бы не использовал его в 99% случаев.

23 голосов
/ 24 апреля 2009

stackalloc относится только к небезопасному коду. Для управляемого кода вы не можете решить, где разместить данные. Типы значений распределяются в стеке по умолчанию (если только они не являются частью ссылочного типа, в этом случае они размещаются в куче). Ссылочные типы размещаются в куче.

Размер стека по умолчанию для простого ванильного приложения .NET составляет 1 МБ, но вы можете изменить это в PE-заголовке. Если вы запускаете потоки явно, вы также можете установить другой размер через перегрузку конструктора. Для приложений ASP.NET размер стека по умолчанию составляет всего 256 КБ, что следует учитывать при переключении между двумя средами.

8 голосов
/ 09 декабря 2018

Stackalloc инициализация пролетов. В предыдущих версиях C # результат stackalloc мог быть сохранен только в локальной переменной указателя. Начиная с C # 7.2, stackalloc теперь может использоваться как часть выражения и может предназначаться для диапазона, и это может быть сделано без использования ключевого слова unsafe. Таким образом, вместо записи

Span<byte> bytes;
unsafe
{
  byte* tmp = stackalloc byte[length];
  bytes = new Span<byte>(tmp, length);
}

Вы можете написать просто:

Span<byte> bytes = stackalloc byte[length];

Это также чрезвычайно полезно в ситуациях, когда для выполнения операции вам нужно немного пустого места, но вы хотите избежать выделения памяти кучи для относительно небольших размеров

Span<byte> bytes = length <= 128 ? stackalloc byte[length] : new byte[length];
... // Code that operates on the Span<byte>

Источник: C # - All About Span: Исследование нового .NET Mainstay

...