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


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

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

3 68

3 ответа:

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

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

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

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

есть несколько других оптимизаций, применяемых компилятором, как описано в /o параметры (оптимизация кода) MSDN docs. Общее описание различных методов оптимизации см. статья оптимизации компилятора Википедии.

с пол Вика блог:

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

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

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

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

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

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