Что делает опция "Оптимизировать код" в Visual Studio?

Имя опции говорит что-то, но что Visual Studio/компилятор действительно делает и каковы реальные последствия?

Изменить: если вы ищете google, вы можете найти этот адрес, но на самом деле я не ищу. Интересно, что происходит. Например, почему циклы получают меньше времени и т.д.

Ответ 1

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

Переменные хранятся в регистрах

Как только вы включаете оптимизацию, компилятор применяет множество различных методов, чтобы заставить код работать быстрее, в то же время делая то же самое. Наиболее очевидное различие между оптимизированными и неоптимизированными сборками в Visual C++ заключается в том, что значения переменных хранятся в регистрах как можно дольше в оптимизированных сборках, в то время как без оптимизации они всегда сохраняются в памяти. Это влияет не только на скорость кода, но и на отладку. В результате этой оптимизации отладчик не может надежно получить значение переменной во время выполнения кода.

Другие оптимизации

Существует несколько других оптимизаций, применяемых компилятором, как описано в документах MSDN "Параметры/O (Оптимизировать код)". Для общего описания различных методов оптимизации см. Статью Wikipedia Compiler Optimization.

Ответ 2

Из Блог Пола Вика:

  • Он удаляет все инструкции NOP, которые в противном случае мы могли бы использовать, чтобы помочь в отладке. Когда оптимизация отключена (и включена информация об отладке), компилятор будет выдавать инструкции NOP для строк, у которых нет фактического ИЛ, связанного с ними, но который вы можете захотеть включить точку останова. Наиболее распространенным примером чего-то подобного будет "End If" оператора "If" - там нет реального IL, испускаемого для End If, поэтому мы не выдаем NOP, отладчик не позволит вам установить точку останова в теме. Включение оптимизации заставляет компилятор не выделять NOP.

  • Мы выполняем простой базовый блок-анализ генерируемого IL для удаления блоков мертвого кода. То есть мы разрываем каждый метод на блоки IL, разделенные инструкциями ветвления. Проводя быстрый анализ того, как блоки взаимосвязаны, мы можем идентифицировать любые блоки, в которых нет ветвей. Таким образом, мы можем вычислить блоки кода, которые никогда не будут выполнены и могут быть опущены, что делает сборку немного меньшей. На данный момент мы также выполняем некоторые небольшие оптимизации ветвей - например, если вы GoTo другой оператор GoTo, мы просто оптимизируем первый GoTo для перехода к второй цели GoTo.

  • Мы выделяем атрибут DebuggableAttribute с параметром IsJITOptimizerDisabled, равным False. В принципе, это позволяет JIT времени выполнения оптимизировать код, как он считает нужным, включая переупорядочивание и встраивание кода. Это приведет к созданию более эффективного и меньшего кода, но это означает, что попытка отладки кода может быть очень сложной (как кто-нибудь, кто попробовал это, скажет вам). Фактический список того, что оптимизация JIT - это то, чего я не знаю, может быть, кто-то вроде Криса Брумме в какой-то момент перезвонит. Длинным и, тем не менее, является то, что оптимизационный коммутатор позволяет оптимизировать, что может сделать установку контрольных точек и более сложную работу над вашим кодом.

Ответ 3

Короткий ответ: use -Ox и пусть компилятор выполнит свою работу.

Длинный ответ: эффект разного рода оптимизаций невозможно точно предсказать. Иногда оптимизация для быстрого кода фактически дает меньший код, чем при оптимизации размера. Если вы действительно хотите получить последние 0,01% производительности (по скорости или по силе), вам нужно сравнить различные комбинации параметров.

Кроме того, в последних версиях Visual Studio есть опции для более продвинутых оптимизаций, таких как оптимизация времени соединения и оптимизация с помощью профиля.