while (condition) {
...
}
Робочий процес:
- перевірити стан;
- якщо false, перейти до зовнішньої частини циклу;
- запустити одну ітерацію;
- стрибнути наверх.
if (condition) do {
...
} while (condition);
Робочий процес:
- перевірити стан;
- якщо хибне, перейти до петель;
- запустити одну ітерацію;
- перевірити стан;
- якщо це так, перейдіть до кроку 3.
Порівнюючи ці два, ви можете легко побачити, що останні можуть взагалі не робити стрибків за умови, що через цикл є рівно один крок, і загалом кількість стрибків буде на один менше, ніж кількість ітерацій. Перший повинен буде відскочити назад, щоб перевірити стан, лише щоб вистрибнути з циклу, коли умова хибна.
Стрибки на сучасних конвеєрних архітектурах процесорів можуть бути досить дорогими: оскільки центральний процесор закінчує виконання перевірок перед стрибком, інструкції після цього стрибка вже знаходяться в середині конвеєра. Вся ця обробка повинна бути відкинута, якщо передбачення гілки не вдається. Подальше виконання затримується, поки трубопровід реформується.
Пояснення згаданого передбачення гілки : для кожного виду умовного стрибка ЦП має дві інструкції, кожна з яких включає ставку на результат. Наприклад, ви б поставили в кінці циклу вказівку " стрибати, якщо не нуль, роблячи ставку на не нуль ", оскільки стрибок повинен бути здійснений на всіх ітераціях, крім останньої. Таким чином, процесор починає прокачувати свій конвеєр з інструкціями, що слідують за ціллю стрибка, замість тих, що слідують за самою інструкцією стрибка.
Важлива примітка
Будь ласка , НЕ приймайте це як приклад того , як оптимізувати на рівні вихідного коду. Це було б цілком помилковим, оскільки, як вже зрозуміло з Вашого запитання, перетворення з першої форми у другу - це те, що компілятор JIT робить, як правило, повністю самостійно.