Вирівнювання даних
Delphi site: daily Delphi-news, documentation, articles, review, interview, computer humor.
Який стосунок має вирівнювання даних до додатків? При програмуванні необхідно переконатися, що змінні типу longint та покажчики вирівняні по чотирибайтовому або 32-бітовому кордоні. Якщо переходять через кордон 4 байт, процесору доведеться видати дві команди на зчитування кеш-пам'яті: перша команда для зчитування першої частини, а друга - другої частини. Потім процесору потрібно з'єднати дві частини значення та відкинути непотрібні біти. (У ряді процесорів 32-бітові значення завжди повинні вирівнюватися по межі 32 біт. В іншому випадку виникає помилка порушення доступу. На щастя, процесори Intel не вимагають цього, що, у свою чергу, провокує програмістів на деяку недбалість.) Завжди переконуйтесь у тому , Що 32-бітові значення вирівняні по межі 32 біт, а 16-бітові значення - по межі 16 біт. Для збільшення швидкодії слід переконатися, що 64-бітові значення (наприклад, змінні типу double) вирівняні по 64-бітовому кордоні.
Автоматичне вирівнювання змінних іноді може ввести програміста в оману. Якщо, наприклад, оголошено наступний тип record у 32-розрядній версії Delphi, яким буде результат виконання операції sizeof (IMyRecord)?
Багато хто без сумніву дасть відповідь, що, мовляв, 5 байт (і це було б правильно для Delphi 1). Однак правильною відповіддю буде 8 байт. Компілятор автоматично вставить три байти між полем aByte та along, просто щоб вирівняти останнє поле по межі 4 байт.
Якщо тип record оголосити так: type TMyRecord = packed record
то функція sizeof (TMyRecord) дасть результат 5. Однак у цьому випадку доступ до поля aLong вимагатиме більше часу, ніж у попередньомуприкладі, оскільки значення поля переходитиме через кордон 4 байт. Отже, правило можна сформулювати так: якщо використовується ключове слово packed, поля запису повинні розташовуватися таким чином, щоб дані були вирівняні по межі 4 байт. Спочатку оголосіть 4-байтні поля, а потім уже всі інші. Це правило застосовується у всіх кодах, наведених у цій книзі. І ще одне, ніколи не вгадуйте розмір запису, а користуйтеся для цього функцією sizeof.
До речі, слід знати, що диспетчер динамічного розподілу пам'яті Delphi допомагає виконувати вирівнювання даних. Він вирівнює не тільки 4-байтні значення за кордоном 4 байт, а й 8-байтні значення за кордоном 8 байт. Це має велике значення для змінних типу double: операції з числами з плаваючою комою виконуються швидше, якщо змінні типу double вирівняні на межі 8 байт. Якщо завдання програмування пов'язані з використанням великої кількості числових змінних, переконайтеся, що поля типу double у записах вирівняні по межі 8 байт.