Различия в производительности между сборками отладки и выпуска - PullRequest
273 голосов
/ 28 октября 2010

Я должен признать, что обычно я не беспокоился о переключении между конфигурациями Debug и Release в моей программе, и я обычно выбирал для Debug конфигурации, даже когда программы фактически развернуты на месте клиента.

Насколько я знаю, единственное различие между этими конфигурациями, если вы не измените его вручную, заключается в том, что Debug имеет постоянную DEBUG, а Release имеет проверенный код Optimize .

Так что мои вопросы на самом деле двойные:

  1. Существуют ли различия в производительности между этими двумя конфигурациями.Есть ли какой-то конкретный тип кода, который может вызвать большие различия в производительности, или это на самом деле не так важно?

  2. Есть ли какой-либо код, который будет нормально работать под * 1028?Отладка конфигурации , которая может завершиться с ошибкой в ​​конфигурации Release , или вы можете быть уверены, что код, проверенный и работающий нормально в конфигурации Debug , также будет работать нормально в конфигурации Release.

Ответы [ 8 ]

503 голосов
/ 28 октября 2010

Сам компилятор C # не сильно изменяет выдаваемый IL в сборке Release.Следует отметить, что он больше не генерирует коды операций NOP, которые позволяют вам установить точку останова на фигурной скобке.Большой - это оптимизатор, который встроен в JIT-компилятор.Я знаю, что это делает следующие оптимизации:

  • Метод встраивания.Вызов метода заменяется введением кода метода.Это большое, оно делает методы доступа к свойствам практически свободными.

  • Распределение регистров процессора.Локальные переменные и аргументы метода могут храниться в регистре ЦП, и никогда (или реже) не сохраняться обратно во фрейм стека.Это большая проблема, которая отличается трудностью отладки оптимизированного кода.И придание ключевому слову volatile значения.

  • Исключение проверки индекса массива.Важная оптимизация при работе с массивами (все классы коллекций .NET используют массив внутри).Когда JIT-компилятор может проверить, что цикл никогда не индексирует массив вне границ, он устраняет проверку индекса.Большой.

  • Развертывание петли.Циклы с маленькими телами улучшаются, повторяя код до 4 раз в теле и зацикливаясь меньше.Снижает стоимость ветвления и улучшает возможности суперскалярного выполнения процессора.

  • Устранение мертвого кода.Утверждение вроде if (false) {/.../} полностью исключается.Это может произойти из-за постоянного складывания и наклона.В других случаях JIT-компилятор может определить, что у кода нет возможных побочных эффектов.Эта оптимизация делает код профилирования таким сложным.

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

  • Устранение общих подвыражений.х = у + 4;z = y + 4;становится z = x;Довольно часто встречается в таких выражениях, как dest [ix + 1] = src [ix + 1];написано для удобства чтения без введения вспомогательной переменной.Не нужно ставить под угрозу удобочитаемость.

  • Постоянное сворачивание.х = 1 + 2;становится х = 3;Этот простой пример рано обнаруживается компилятором, но происходит во время JIT, когда другие оптимизации делают это возможным.

  • Копирование распространения.х = а;у = х;становится у = а;Это помогает распределителю регистра принимать лучшие решения.Это большая проблема в джиттере x86, потому что у него мало регистров для работы.Выбор правильных из них имеет решающее значение для перфектов.

Это очень важные оптимизации, которые могут иметь огромное значение , когда, например, вы профилируетеОтладьте сборку вашего приложения и сравните ее с версией выпуска.Это действительно имеет значение, хотя, когда код находится на вашем критическом пути, от 5 до 10% кода, который вы пишете, на самом деле , влияет на производительность вашей программы.Оптимизатор JIT не настолько умен, чтобы заранее знать, что критично, он может применять только «поворот на одиннадцать» для всего кода.

Эффективный результат этих оптимизаций для времени выполнения вашей программы часто зависит от кода, который выполняется в другом месте.Чтение файла, выполнение запроса к базе данных и т. Д. Выполнение работы оптимизатором JIT делает полностью незаметным.Хотя это не против:)

JIT-оптимизатор - это довольно надежный код, в основном потому, что он был проверен миллионы раз.Очень редко возникают проблемы в версии сборки вашей версии.Это случается однако.У xit и x86 jitters были проблемы со структурами.Джиттер x86 имеет проблемы с согласованностью с плавающей запятой, приводя к несколько иным результатам, когда промежуточные значения вычисления с плавающей запятой хранятся в регистре FPU с 80-битной точностью вместо усечения при сбросе в память.

23 голосов
/ 28 октября 2010
  1. Да, есть много различий в производительности, и они действительно применяются во всем вашем коде.Отладка очень мало оптимизирует производительность, а режим выпуска очень сильно;

  2. Только код, основанный на константе DEBUG, может работать по-разному в сборке выпуска.Кроме того, вы не должны видеть никаких проблем.

Примером кода платформы, который зависит от константы DEBUG, является метод Debug.Assert(), для которого определен атрибут [Conditional("DEBUG)"],Это означает, что это также зависит от константы DEBUG и не включено в сборку релиза.

12 голосов
/ 28 октября 2010

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

Однако, если у вас много вычислений, требующих большого объема вычислений, вы заметите различиядо 40%, как упомянул @Pieter, хотя это будет зависеть от характера расчетов).

По сути, это компромиссный дизайн.Если вы выпускаете под сборкой DEBUG, то, если у пользователей возникают проблемы, вы можете получить более значимый след и вы можете сделать гораздо более гибкую диагностику.Выпуская в сборке DEBUG, вы также избегаете оптимизатора, производящего малоизвестные Heisenbugs .

11 голосов
/ 28 октября 2010
  • Мой опыт показывает, что средние или большие приложения заметно более отзывчивы в сборке выпуска.Попробуйте его в своем приложении и посмотрите, как оно выглядит.

  • Одна вещь, которая может укусить вас в сборках Release, заключается в том, что код отладочной сборки может иногда подавлять условия гонки и другие ошибки, связанные с многопоточностью.,Оптимизированный код может привести к переупорядочению команд, а более быстрое выполнение может усугубить определенные условия гонки.

9 голосов
/ 29 октября 2010

Вы никогда не должны выпускать сборку .NET Debug в производство. Она может содержать некрасивый код для поддержки редактирования и продолжения или кто знает что еще. Насколько я знаю, это происходит только в VB, а не в C # (примечание: исходное сообщение помечено C #) , но это все равно должно дать повод задуматься над тем, что, по мнению Microsoft, им разрешено делать с Отладочная сборка. Фактически, до .NET 4.0, код VB теряет память, пропорциональную количеству экземпляров объектов с событиями, которые вы создаете для поддержки редактирования и продолжения. (Хотя сообщается, что это исправлено в https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging,, сгенерированный код выглядит мерзко, создавая WeakReference объекты и добавляя их в статический список, в то время как удерживает блокировку ) Я определенно не хочу любой из этих видов поддержки отладки в производственной среде!

5 голосов
/ 28 октября 2010

По моему опыту, худшее, что вышло из режима Release, - это скрытые "ошибки выпуска". Поскольку IL (промежуточный язык) оптимизирован в режиме Release, существует возможность ошибок, которые не проявились бы в режиме Debug. Есть и другие вопросы, касающиеся этой проблемы: Распространенные причины ошибок в версии выпуска, отсутствующих в режиме отладки

Это случалось со мной один или два раза, когда простое консольное приложение прекрасно работало в режиме отладки, но при одинаковом входном значении приводило к ошибке в режиме выпуска. Эти ошибки ЧРЕЗВЫЧАЙНО трудно устранить (по иронии судьбы, по определению режима Release).

3 голосов
/ 28 октября 2010

Я бы сказал, что 1) во многом зависит от вашей реализации.Обычно разница не так велика.Я сделал много измерений, и часто я не мог видеть разницу.Если вы используете неуправляемый код, множество огромных массивов и тому подобное, разница в производительности немного больше, но это не другой мир (как в C ++).2) Обычно в коде выпуска отображается меньше ошибок (более высокий допуск), поэтому переключатель должен работать нормально.

0 голосов
/ 17 декабря 2015
    **Debug Mode:**
    Developer use debug mode for debugging the web application on live/local server. Debug mode allow developers to break the execution of program using interrupt 3 and step through the code. Debug mode has below features:
   1) Less optimized code
   2) Some additional instructions are added to enable the developer to set a breakpoint on every source code line.
   3) More memory is used by the source code at runtime.
   4) Scripts & images downloaded by webresource.axd are not cached.
   5) It has big size, and runs slower.

    **Release Mode:**
    Developer use release mode for final deployment of source code on live server. Release mode dlls contain optimized code and it is for customers. Release mode has below features:
    More optimized code
    Some additional instructions are removed and developer can’t set a breakpoint on every source code line.
   1) Less memory is used by the source code at runtime.
   2) Scripts & images downloaded by webresource.axd are cached.
   3) It has small size, and runs fast.
   4) Scripts & images downloaded by webresource.axd are cached.
   5) It has small size, and runs fast.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...