Большинство современных процессоров поддерживают прогнозирование ветвей. Они имеют небольшой кэш, который позволяет процессору условно дать вам преимущества переупорядочения во время выполнения. Этот кэш довольно ограничен по размеру, но может означать, что вы не получите столько пользы, сколько можете себе представить. Некоторые процессоры могут даже начать выполнять обе ветви и отбросить работу, выполненную на не выполненной ветви.
РЕДАКТИРОВАТЬ: Наибольшее преимущество в использовании JIT-компилятора заключается в таком коде.
if (debug) {
// do something
}
JIT очень хороши для обнаружения и оптимизации кода, который ничего не делает. (Если у вас есть микро-тест, который предполагает, что Java намного быстрее, чем C, скорее всего, JIT обнаружил, что ваш тест ничего не делает, а компилятор C этого не сделал)
Вы можете спросить, почему у C нет чего-то подобного? Потому что есть что-то "лучшее"
#if DEBUG
// do something
#endif
Это оптимально, если DEBUG редко изменяется, и у вас очень мало таких флагов, так что вы можете скомпилировать каждую полезную комбинацию.
Проблема этого подхода в масштабируемости. Каждый добавленный вами флаг может удвоить количество предварительно скомпилированных двоичных файлов.
Если у вас много таких флагов и нецелесообразно компилировать каждую комбинацию, вам нужно полагаться на предсказание ветвлений для динамической оптимизации кода.