Я понимаю, что небезопасный код более подходит для доступа к таким вещам, как API Windows, и делает небезопасные типы отливок, чем писать более эффективный код, но я хотел бы спросить вас, заметили ли вы когда-либо значительное повышение производительности в реальных приложениях используя его по сравнению с безопасным кодом С#.
Неверная производительность кода
Ответ 1
Некоторые измерения производительности
Преимущества производительности не так велики, как вы думаете.
Я сделал некоторые измерения производительности обычного доступа к управляемому массиву против небезопасных указателей на С#.
Результаты выполнения сборки за пределами Visual Studio 2010,.NET 4, используя Любой процессор | Разверните версию на следующей спецификации ПК: x64-based ПК, 1 четырехъядерный процессор. Intel64 Family 6 Model 23 Stepping 10 GenuineIntel ~ 2833 Mhz.
Linear array access 00:00:07.1053664 for Normal 00:00:07.1197401 for Unsafe *(p + i) Linear array access - with pointer increment 00:00:07.1174493 for Normal 00:00:10.0015947 for Unsafe (*p++) Random array access 00:00:42.5559436 for Normal 00:00:40.5632554 for Unsafe Random array access using Parallel.For(), with 4 processors 00:00:10.6896303 for Normal 00:00:10.1858376 for Unsafe
Обратите внимание, что небезопасная идиома *(p++)
на самом деле работает медленнее. Я предполагаю, что это нарушило оптимизацию компилятора, которая объединяла переменную цикла и доступ к указателю (сгенерированный компилятором) в безопасной версии.
Исходный код доступен на github.
Ответ 2
Хорошим примером являются манипуляции с изображениями. Изменение пикселов с помощью указателя на их байты (что требует небезопасного кода) довольно быстро.
Пример: http://www.gutgames.com/post/Using-Unsafe-Code-for-Faster-Image-Manipulation.aspx
Если говорить, что для большинства сценариев разница не будет столь заметной. Поэтому, прежде чем использовать небезопасный код, профайл приложения, чтобы узнать, где узкие места производительности и проверить, действительно ли безопасный код является решением, чтобы сделать его быстрее.
Ответ 3
Как было указано в других сообщениях, вы можете использовать небезопасный код в очень специализированных контекстах, чтобы получить значительное повышение производительности. Один из этих сценариев - итерация по массивам типов значений. Использование небезопасной арифметики указателя намного быстрее, чем использование обычного шаблона for-loop/indexer.
struct Foo
{
int a = 1;
int b = 2;
int c = 0;
}
Foo[] fooArray = new Foo[100000];
fixed (Foo* foo = fooArray) // foo now points to the first element in the array...
{
var remaining = fooArray.length;
while (remaining-- > 0)
{
foo->c = foo->a + foo->b;
foo++; // foo now points to the next element in the array...
}
}
Основное преимущество здесь в том, что мы полностью отключили проверку индекса массива.
В то время как очень эффективный, этот тип кода трудно обрабатывать, может быть довольно опасным (небезопасным) и нарушает некоторые фундаментальные рекомендации (изменчивая структура). Но есть, конечно, сценарии, где это подходит...
Ответ 4
Хорошо, я бы предложил прочитать этот блог-пост: Блоги MSDN: Проверка границ массива Исправление в среде CLR
Это разъясняет, как в С# выполняются проверки границ. Более того, тесты Томаса Братца кажутся мне бесполезными (смотря на код), так как JIT удаляет в своих "save" петлях ограничения-так или иначе.
Ответ 5
Я использую небезопасный код для кода манипуляции видео. В таком коде вы хотите, чтобы он работал как можно быстрее, без внутренних проверок значений и т.д. Без небезопасных атрибутов мой способ не мог бы идти в ногу с видеопотоком со скоростью 30 кадров в секунду или 60 кадров в секунду. (в зависимости от используемой камеры).
Но из-за скорости его широко используют люди, которые кодируют графику.