Управление памятью C#: небезопасное ключевое слово и указатели

Что последствия (положительны/отрицательны) относительно использования небезопасного ключевого слова в C# для использования указателей? Например, что случилось со сборкой "мусора", каковы усиления/потери производительности, каковы усиления/потери производительности по сравнению с другим управлением памятью руководства языков, каковы опасности, в которой ситуации это действительно допустимо для использования этой функции языка, это длиннее для компиляции...?

33
задан Alerty 22 March 2010 в 22:53
поделиться

4 ответа

Как уже упоминал Конрад, есть некоторые ситуации, когда небезопасно доступ к памяти в C # полезен.Их не так много , но есть некоторые:

  • Управление с помощью Bitmap - почти типичный пример, когда вам нужна дополнительная производительность, которую вы можете получить, используя ] небезопасно .

  • Взаимодействие со старым API (таким как WinAPI или собственные библиотеки C / C ++) - еще одна область, где небезопасный может быть весьма полезен - например, вы можете захотеть вызвать функцию, которая принимает / возвращает неуправляемый указатель.

С другой стороны, вы можете написать большинство вещей, используя Marshall class , который скрывает многие небезопасные операции внутри вызовов методов. Это будет немного медленнее, но это вариант, если вы хотите избежать использования unsafe (или если вы используете VB.NET, в котором нет unsafe )

Положительные последствия : Итак, основные положительные последствия существования unsafe в C # заключаются в том, что вы можете легче писать некоторый код (совместимость) и вы можете писать больше кода эффективно (манипулирование растровым изображением или, возможно, некоторые тяжелые числовые вычисления с использованием массивов - хотя я не уверен насчет второго).

Отрицательные последствия : Конечно, есть определенная цена, которую вы должны заплатить за использование unsafe :

  • Неверифицируемый код : код C #, написанный с использованием небезопасные функции становятся недоступными для проверки, что означает, что ваш код может каким-либо образом скомпрометировать среду выполнения. Это не большая проблема в сценарии с полным доверием (например, неограниченное настольное приложение) - у вас просто нет всего хорошего.NET CLR гарантирует. Однако вы не можете запускать приложение в ограниченной среде, такой как общедоступный веб-хостинг, Silverlight или частичное доверие (например, приложение, работающее из сети).

  • Сборщик мусора также должен быть осторожен, когда вы используете unsafe . GC обычно разрешается перемещать объекты в управляемой куче (чтобы память оставалась дефрагментированной). Когда вы берете указатель на какой-либо объект, вам нужно использовать ключевое слово fixed , чтобы сообщить GC, что он не может переместить объект, пока вы не закончите (что, вероятно, может повлиять на производительность сборки мусора - но, конечно, в зависимости от конкретного сценария).

Я предполагаю, что, если бы C # не взаимодействовал со старым кодом, он, вероятно, не поддерживал бы unsafe (и исследовательские проекты, такие как Singularity, которые пытаются создать более проверяемую операционную систему на основе управляемых языков, безусловно, запретить код usnsafe). Однако в реальном мире unsafe полезен в некоторых (редких) случаях.

27
ответ дан 27 November 2019 в 18:33
поделиться

Я могу дать вам ситуацию, в которой его стоило использовать:

Мне нужно сгенерировать растровое изображение пиксель за пикселем. Drawing.Bitmap.SetPixel () работает слишком медленно. Поэтому я создаю свой собственный управляемый массив растровых данных и использую unsafe , чтобы получить IntPtr для Bitmap.Bitmap (Int32, Int32, Int32, PixelFormat, IntPtr) .

9
ответ дан 27 November 2019 в 18:33
поделиться

Цитирую Professional C# 2008:

"Две основные причины для использования указателей являются:

  1. Обратная совместимость - Несмотря на все возможности, предоставляемые .NET-исполнением, все еще возможно вызывать родные функции Windows API, и для некоторых операций это может быть единственным способом выполнения задачи. Эти API-функции обычно написаны на языке C и часто требуют указатели в качестве параметров. Однако во многих случаях можно написать объявление DllImport таким образом, чтобы избежать использования указателей; например, используя класс System.IntPtr.
  2. Производительность - В тех случаях, когда скорость имеет первостепенное значение. важность, указатель может обеспечить путь к оптимизированной производительности. Если вы знаете, что делаете, вы можете обеспечить доступ к данным или манипулирование данными наиболее эффективным способом. Однако имейте в виду, что чаще всего чаще всего существуют другие области вашего кода, где вы можете сделать необходимые повышения производительности без обращения к указателям. Попробуйте использовать профилировщик кода для поиска узких мест в вашем коде - один из них поставляется с Visual Studio 2008."

И если вы используете указатели, ваш код будет требовать более высокого уровня доверия для выполнения, и если пользователь не предоставит такого доверия, ваш код не будет выполняться.

И завершим последнюю цитату:

"Мы настоятельно рекомендуем не использовать указатели без необходимости, потому что это будет не только будет сложнее писать и отлаживать, но и не справится с проверки на безопасность типов памяти, налагаемые CLR."

5
ответ дан 27 November 2019 в 18:33
поделиться

Сборка мусора неэффективна с долгоживущими объектами. Сборщик мусора .Net работает лучше всего, когда большинство объектов освобождаются довольно быстро, а некоторые объекты «живут вечно». Проблема в том, что долгоживущие объекты освобождаются только во время полной сборки мусора, что значительно снижает производительность. По сути, долгоживущие объекты быстро переходят в поколение 2.

(Для получения дополнительной информации вы можете почитать о сборщике мусора поколений .Net: http://msdn.microsoft.com/en-us /library/ms973837.aspx)

В ситуациях, когда объекты или использование памяти в целом будет долгоживущим, ручное управление памятью даст более высокую производительность, поскольку оно может быть передано в систему, не требуя полная сборка мусора.

Реализация какой-то системы управления памятью, основанной на одном большом массиве байтов, структурах и большом количестве арифметических операций с указателями, теоретически может повысить производительность в ситуациях, когда данные будут храниться в ОЗУ в течение длительного времени.

К сожалению, я не знаю хорошего способа ручного управления памятью в .Net для объектов, которые будут долгоживущими. По сути, это означает, что приложения, которые имеют долговременные данные в ОЗУ, будут периодически перестать отвечать, когда они запускают полную сборку мусора для всей памяти.

2
ответ дан 27 November 2019 в 18:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: