В первых компьютерах всё было просто. Процессор читал данные по одному байту, и этого хватало. Программ было мало, память маленькая, и никто не задумывался о правилах хранения. Но со временем задачи стали сложнее. Читать по одному байту оказалось слишком медленно. Пришлось брать данные кусками — блоками. Это ускорило работу, но принесло новые трудности.
Сначала процессор начал спотыкаться, когда данные лежали «криво», не по границе блока. Потом выяснилось, что разные процессоры по-разному раскладывают байты внутри числа. А позже к этому добавилось новое ограничение — границы страниц памяти. Каждое из этих затруднений требовало своего решения.
Компьютер не работает с памятью по одному биту. Он всегда берёт данные кусками — блоками. Минимальный кусок — байт. Но процессор может читать и больше: слова, двойные слова и целые строки. Размер блока задаёт, сколько информации переносится за одну операцию.
Представим процессор, который читает по 4 байта за раз. В памяти лежит число AB CD EF 01
. Оно начинается с адреса, кратного четырём. Процессор делает одно чтение и получает сразу всё число.
Теперь другое число — 23 45 67 89
. Но оно начинается с адреса 2. В первом блоке памяти процессор видит .. 23 45 67
, во втором — 89 .. .. ..
. Чтобы собрать число целиком, приходится читать два блока. Работа замедляется.
Поэтому придумали правило выравнивания. Если число занимает 4 байта, оно должно начинаться с адреса, делящегося на 4. Так процессор работает быстрее и проще.
Размер блока напрямую влияет на скорость. Большие блоки позволяют переносить больше данных за раз, но иногда программа запрашивает совсем маленький кусок и занимает лишнее. Если блоки слишком маленькие, система тратит время на их объединение. Баланс между этими крайностями задаёт сама архитектура компьютера.
Возьмём число 0x12345678
. В памяти оно может храниться по-разному:
- Little-endian:
78 56 34 12
- Big-endian:
12 34 56 78
Для человека это одно и то же число. Но процессор читает байты по-своему. Если данные записаны в little-endian, а процессор ожидает big-endian, то вместо 0x12345678
он получит 0x78563412
.
Такое расхождение особенно заметно в сетях и протоколах: если стороны не договорились о порядке байтов, данные окажутся искажёнными.
Современные операционные системы делят память на страницы фиксированного размера, например по 4 КБ. Это удобно для управления и защиты, но создаёт новую проблему.
Представим структуру размером 512 байт. Если она начинается в начале страницы, то целиком помещается внутрь неё. Но если структура начинается за 100 байт до конца страницы, то оставшиеся 412 байт перепрыгивают на следующую страницу. Теперь процессору приходится обращаться к двум страницам вместо одной. Это значит лишние операции и больше времени.
Если не учитывать эти правила, появляются странные ошибки и падения. Выравнивание может превратить простую операцию в двойное чтение. Разный порядок байтов — в искажение чисел. А пересечение границы страниц — в неожиданные тормоза программы. Эти ошибки сложно заметить, но они напрямую влияют на производительность.
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.