Практическое использование ключевого слова `stackalloc`

StackOverflow https://stackoverflow.com/questions/785226

  •  16-09-2019
  •  | 
  •  

Вопрос

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

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

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

Есть ли какие-то практические случаи, когда можно было бы сказать:"это именно тот объем данных и обработки, который мне нужен, чтобы стать небезопасным и использовать stackalloc"?

Это было полезно?

Решение

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

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

Другие советы

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

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

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

Stackalloc инициализация сегментов.В предыдущих версиях C # результат stackalloc мог быть сохранен только в локальной переменной указателя.Начиная с C # 7.2, stackalloc теперь можно использовать как часть выражения и может быть нацелен на span, и это может быть сделано без использования ключевого слова 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 # - Все о Span:Изучение Новой основы .NET

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top