Первоначально (например, 8086) стоимость перехода не сильно отличалась от стоимости mov
.
. Более поздние процессоры добавили кеш, что означало, что некоторые переходы были быстрее (потому что код, который они прыгаютto находится в кеше) и некоторые переходы были медленнее (потому что код, к которому они переходят, не находятся в кеше).
Даже позже ЦП добавили выполнение «не в порядке», где условные переходы (например, je SOME_LOCATION
) придется подождать, пока не станут известны флаги «предыдущих команд, которые выполняются параллельно».
Это означает, что последовательность типа
mov esi, edi
cmp ecx, edx
je SOME_LOCATION
может быть медленнее, чем перестановка ее в
cmp ecx, edx
mov esi, edi
je SOME_LOCATION
, чтобы увеличить вероятность того, что флаги будут известны.
Еще позже процессоры добавили спекулятивное выполнение.В этом случае для условных переходов ЦП просто делает предположение о том, куда он будет переходить, прежде чем он на самом деле узнает (например, до того, как флаги станут известны), и, если он угадает, он просто сделает вид, что не выполнил неправильноеинструкции.Более конкретно, спекулятивно выполняемые инструкции помечаются в начале конвейера и удерживаются в конце конвейера (при выходе из системы) до тех пор, пока ЦП не узнает, могут ли они быть зафиксированы в видимом состоянии или их нужно отбросить.
После этого все стало еще сложнее, с более изощренными методами прогнозирования ветвлений, дополнительными буферами "цели перехода" и т. Д.
Дальнейшие переходы, которые изменяют сегмент кода, обходятся дороже.В реальном режиме это не так уж и плохо, потому что ЦП в основном выполняет «CS.base = значение * 16» только при изменении CS
.Для защищенного режима это поиск в таблице (чтобы найти запись GDT или LDT), декодирование записи, решение, что делать в зависимости от типа записи, а затем куча проверок защиты.Для длинного режима это смутно похоже.Все это добавляет больше неопределенности (например, если запись таблицы находится в кеше?).
Помимо всего этого есть такие вещи, как пропуск TLB.Например, jmp [indirectAddress]
может вызвать промах TLB в indirectAddress
, затем промах TLB в верхней части стека, а затем промах TLB в новом указателе инструкций;где каждый промах TLB может стоить несколько сотен циклов.
В основном;стоимость прыжка может составлять от 0 циклов (для правильно предсказанного прыжка) до 1000 циклов;в зависимости от того, какой это процессор, какой скачок, что находится в кеше, какой прогноз предсказания ветвлений, пропадание кеша / TLB, как быстро / медленно работает RAM, и все, что я мог забыть.