Unsafe.SkipInit для структур #скорость
Как раз на конференции, в кулуарах, спрашивали про
Как я уже говорил, это решение следующей проблемы:
1. Выделяется память.
2. Эта память заполняется дефолтными значениями (чтобы программист не получил в значениях полей структуры явную тарабарщину от предыдущих пользователей памяти). Условно
3. Память, в виде структуры, отдаётся пользователю (программисту). В классическом варианте, программист получит в числовом поле 0 (deafult), а в ссылочном - null.
Вот
Кстати, обратите внимание на разницу в .NET 8 и .NET 9.
Коллеги работают!
P.S.: Про массивы читать тут.
Как раз на конференции, в кулуарах, спрашивали про
Unsafe.SkipInit
. Набросал бенчмарк, который будет в комментариях.Как я уже говорил, это решение следующей проблемы:
1. Выделяется память.
2. Эта память заполняется дефолтными значениями (чтобы программист не получил в значениях полей структуры явную тарабарщину от предыдущих пользователей памяти). Условно
0000000000
.3. Память, в виде структуры, отдаётся пользователю (программисту). В классическом варианте, программист получит в числовом поле 0 (deafult), а в ссылочном - null.
Вот
Unsafe.SkipInit
говорит, мол, господин рантайм, я и сам заполню все значения. Ну или, в смысле доклада, я и сам знаю какая область памяти мне нужна как инициализированная. То есть п.2 не выполняется. Что заметно улучшает скорость. Документация тут, там есть интересные примеры.Кстати, обратите внимание на разницу в .NET 8 и .NET 9.
Коллеги работают!
P.S.: Про массивы читать тут.
🔥16👍3
Function pointer #скорость
Представим, что у нас есть подсистема вычисления. Один класс отвечает за выбор операции над значениями, а другой производит магию вычисления с использованием выбранной операции. В каждом из классов какая-то сложная логика, поэтому объединить их нельзя или сложно.
Пример: операции над формулами в Excel - до того как мы прочитаем формулу, мы не знаем, какая операция будет произведена над ячейками.
Условно, это выглядит вот так:
Это работает быстро, но, благодаря "современному" C# (function pointer'ы появились аж 5 лет назад), подобные сценарии можно ускорить на 10-15%. Для этого нужно уйти в лёгкий
Этот финт даёт нам возможность выразить следующую мысль: уважаемый компилятор и рантайм, мы точно знаем расположение функции в памяти (указатель), пожалуйста, не трать время, а просто дёрни то, что сказал тебе умный программист.
Для библиотечного кода такой unsafe весьма оправдан (так как даёт хороший буст производительности). В случае обычного энтерпрайз-кода я бы такое не использовал никогда.
Бенчмарк тут, чтобы каждый мог убедиться, что мы действительно получаем профит.
P.S.: Коллега напоминает, что ещё function pointer удобен для работы с библиотекам на других технологиях.
Представим, что у нас есть подсистема вычисления. Один класс отвечает за выбор операции над значениями, а другой производит магию вычисления с использованием выбранной операции. В каждом из классов какая-то сложная логика, поэтому объединить их нельзя или сложно.
Пример: операции над формулами в Excel - до того как мы прочитаем формулу, мы не знаем, какая операция будет произведена над ячейками.
Условно, это выглядит вот так:
MathOperation operation = SelectOperation(Context);
Func<int, int, int> executor = operation switch {
MathOperation.Add => MathOperations.Add,
MathOperation.Subtract => MathOperations.Subtract,
MathOperation.Multiply => MathOperations.Multiply,
MathOperation.Divide => MathOperations.Divide,
_ => Error.NotSupportedOperation(operation, Context)
};
Calculator.Execute(executor, xValue, yValue);
Это работает быстро, но, благодаря "современному" C# (function pointer'ы появились аж 5 лет назад), подобные сценарии можно ускорить на 10-15%. Для этого нужно уйти в лёгкий
unsafe
, и заменить Func<int, int, int>
на delegate*<int, int, int>
. Мотивацию появления этого улучшения можно подсмотреть тут.Этот финт даёт нам возможность выразить следующую мысль: уважаемый компилятор и рантайм, мы точно знаем расположение функции в памяти (указатель), пожалуйста, не трать время, а просто дёрни то, что сказал тебе умный программист.
Для библиотечного кода такой unsafe весьма оправдан (так как даёт хороший буст производительности). В случае обычного энтерпрайз-кода я бы такое не использовал никогда.
Бенчмарк тут, чтобы каждый мог убедиться, что мы действительно получаем профит.
P.S.: Коллега напоминает, что ещё function pointer удобен для работы с библиотекам на других технологиях.
🔥13👍7😁1👀1