Числа, которые должен знать каждый инженер
Иерархия задержек — L1 ~1нс, RAM ~100нс, SSD ~16мкс, RTT в ЦОД ~0,5мс, disk seek ~10мс, межрегион ~150мс — охватывает восемь порядков. Запомни отношения, и сможешь отвергнуть дизайн в голове, не строя его.
Staff-инженер ревьюит дизайн-док, где предлагают синхронный вызов на каждый запрос из сервиса в Вирджинии к базе во Франкфурте — «это же всего один лишний запрос». Не открывая калькулятор, он отвергает: трансатлантический round-trip ~150 мс, значит этот «один лишний запрос» добавляет 150 мс к каждому запросу, а страница, делающая три таких, — это уже полсекунды чистого ожидания сети. Ни бенчмарка, ни прототипа — только число в голове и отношение: межрегион ~в 300× дороже внутридатацентрового прыжка. Числа, которые должен знать каждый инженер, — не мелочь для эрудиции; это фильтр дизайна, работающий в голове со скоростью разговора.
Иерархия задержек
Спроси себя: сколько реально занимает чтение из RAM против диска, или вызов сервиса в другом регионе? Если не можешь ответить с точностью до порядка — будешь пропускать медленные дизайны не замечая. Вот таблица, которая это исправляет.
Любая операция системы лежит где-то на лестнице, охватывающей примерно восемь порядков — от попадания в кэш, что фактически бесплатно, до межконтинентального round-trip (круговой задержки между регионами), что целая вечность. Каноническая таблица Джеффа Дина «числа задержек, которые должен знать каждый программист» — позвоночник этой лестницы. Округлённо до важных порядков:
Обращение к L1-кэшу ~1 нс (0,5 нс)
Branch mispredict ~5 нс
Обращение к L2-кэшу ~7 нс
Обращение к основной памяти (RAM) ~100 нс (~100× медленнее L1)
Чтение 1 МБ последовательно из RAM ~250 мкс (250 000 нс)
Случайное чтение с SSD ~16 мкс (~150× медленнее RAM)
Round-trip внутри ЦОД ~0,5 мс (500 000 нс)
Disk seek (HDD) ~10 мс (~20× round-trip в ЦОД)
Чтение 1 МБ последовательно с диска ~30 мс
Round-trip CA → Нидерланды → CA ~150 мс (межрегион)Абсолютные числа дрейфуют с поколениями железа — в исходной таблице Дина 2010 года не было строки SSD, а современный NVMe быстрее этих ~16 мкс — но отношения устойчивы, и именно их запоминают. RAM ~в 100× медленнее L1. SSD ~в 100–150× медленнее RAM, но ~в 1000× быстрее disk seek HDD. Сетевой round-trip внутри ЦОД (~0,5 мс) ~в 5000× дороже обращения к RAM. Межрегиональный round-trip (~150 мс) ~в 300× дороже внутридатацентрового и задаётся скоростью света, так что никакой апгрейд железа его не починит.
▸Почему это работает
Почему межрегиональное число — это пол, который не обойти инженерией? Потому что это физика, а не медленное оборудование. Свет в оптоволокне идёт примерно на двух третях c (~200 000 км/с). Калифорния — Нидерланды и обратно — ~18 000 км кабеля, это ~90 мс чистого распространения минимум, до того как роутер, очередь или TLS-рукопожатие добавят ещё — итого около 150 мс на практике. Можно купить быстрее CPU, быстрее диски, больше полосы; нельзя купить более короткий путь сквозь пространство-время. Поэтому «просто поставь реплику в каждом регионе» и «никогда не делай синхронный межрегиональный вызов на пути запроса» — не предпочтения, а следствия единственного числа в таблице, которое железо никогда не улучшит.
Как они масштабируются друг относительно друга
Самый полезный мысленный приём — известный как масштаб «если бы наносекунда была секундой» — растянуть лестницу в человеческое время, чтобы зазоры стали осязаемы. Умножь всё на ~10^9:
- L1-кэш (~1 нс) → 1 секунда.
- RAM (~100 нс) → ~2 минуты.
- Чтение SSD (~16 мкс) → ~4,5 часа.
- Round-trip в ЦОД (~0,5 мс) → ~6 дней.
- Disk seek (~10 мс) → ~4 месяца.
- Межрегиональный round-trip (~150 мс) → ~5 лет.
Теперь «читает из RAM вместо диска» перестаёт быть абстракцией: это разница между 2-минутным поручением и 4-месячной экспедицией. Поэтому существует кэширование, поэтому горячий рабочий набор в памяти стоит так дорого и поэтому одна случайная disk seek (перемещение считывающей головки к нужной дорожке, ~10 мс) или межрегиональный прыжок на пути запроса может доминировать над всем остальным вместе взятым. Урок из оценки — найди, какой шаг доминирует — это ровно применение этой таблицы: самый медленный уровень на пути задаёт пол.
Порядки пропускной способности, а не только задержки
Задержка — «сколько на один»; пропускная способность — «сколько в секунду», и у неё своя грубая лестница, которую стоит носить:
- Последовательная полоса RAM: десятки ГБ/с на сокет.
- NVMe SSD: ~3–7 ГБ/с последовательно, сотни тысяч IOPS (операций ввода-вывода в секунду).
- HDD: ~100–200 МБ/с последовательно, но всего ~100 случайных seek/с — случайный I/O это где диски умирают.
- Сеть: NIC на 10 Гбит/с двигает ~1,25 ГБ/с; 25/100 Гбит/с в современных ЦОД.
- Один хорошо настроенный сервис: низкие десятки тысяч простых запросов/с на CPU-связанную машину — разумная стартовая точка по порядку.
Важная пара: последовательный доступ на один-два порядка быстрее случайного и на дисках, и (в меньшей степени) в памяти, потому что последовательные чтения амортизируют цену seek/подготовки и используют prefetch. «Сделай паттерн доступа последовательным» — один из самых рычажных ходов по производительности именно из-за этого отношения.
Используя числа, чтобы дёшево отвергать дизайн
Выигрыш — дешёвый отсев: убить плохой дизайн в одном предложении вместо спринта. Несколько паттернов, что таблица опровергает мгновенно:
- «Будем читать с диска на каждый запрос при 50К QPS». HDD делает ~100 случайных seek/с; нужно ~500 дисков. Дизайн мёртв — кэшируй или используй SSD/RAM.
- «Один синхронный межрегиональный вызов на запрос — норм». Он добавляет ~150 мс к каждому запросу, пол. Перенеси данные ближе или сделай вызов асинхронным.
- «N+1 запросов, но они быстрые». 100 последовательных внутридатацентровых round-trip × 0,5 мс = 50 мс чистого ожидания сети до любой работы. Батчи их.
- «Цикл по 10М строк в приложении вместо SQL». Если каждая строка — это fetch, это 10М round-trip; отношение между работой в процессе и по сети — в тысячи раз. Толкай работу к данным.
У всех этих паттернов одна общая черта: они пересекают медленную границу много раз, когда хватило бы одного раза (или нуля). Когда видишь дизайн, где удалённый ресурс вызывается поштучно в цикле, таблица даёт отказ за секунды — без бенчмарка.
▸Частая ошибка
Ловушка — считать эти числа статичными абсолютами и либо чрезмерно доверять устаревшим цифрам, либо отказываться их использовать, потому что «железо изменилось». Оба мимо. Цифра чтения RAM у Дина из 2010 предшествует DDR5; NVMe пробил строку SSD; облачная задержка между AZ отличается от его контекста одной машины. Но отношения и порядки — RAM ≫ SSD ≫ disk-seek, внутри-ЦОД ≫ межрегион в ~300×, последовательный ≫ случайный — держатся десятилетиями и будут держаться, потому что отражают физику и архитектуру, а не поколение продукта. Запомни порядки величин и отношения; перемерь абсолюты для своего реального железа, когда решение близкое.
Примерно во сколько раз обращение к основной памяти (RAM) медленнее обращения к L1-кэшу, и во сколько раз межрегиональный round-trip медленнее внутридатацентрового?
Дизайн предлагает читать записи со шпиндельного HDD случайными seek при цели 20 000 чтений/с. Используя числа в голове, каков вердикт?
Межрегиональный round-trip (~150 мс) — пол, который не обойти инженерией, потому что он задаётся скоростью _______ в оптоволокне на тысячах километров — можно купить быстрее CPU и диски, но не более короткий путь сквозь пространство-время.
- 01Перечисли иерархию задержек и важные отношения.
- 02Почему число ~150 мс межрегиона — то, что железо никогда не починит?
- 03Назови два дизайна, что числа позволяют отвергнуть в одном предложении, и почему.
Числа, которые должен знать каждый инженер, образуют иерархию задержек, охватывающую примерно восемь порядков: L1 ~1 нс, RAM ~100 нс, случайное чтение SSD ~16 мкс, round-trip внутри ЦОД ~0,5 мс, disk seek HDD ~10 мс, межрегиональный round-trip ~150 мс. Абсолютные значения дрейфуют с каждым поколением железа, но отношения устойчивы и именно их запоминают — RAM ~в 100× дороже L1, SSD ~в 150× дороже RAM, но ~в 1000× быстрее disk seek, а межрегиональный прыжок ~в 300× дороже внутридатацентрового. Это последнее число — пол скорости света, который не обойти инженерией, поэтому межрегиональным вызовам не место на пути запроса. Есть параллельная лестница пропускной способности (RAM десятки ГБ/с, NVMe ГБ/с, HDD ~100 случайных seek/с, NIC 10 Гбит/с ~1,25 ГБ/с), чей ключевой урок — последовательный бьёт случайный на один-два порядка. Носимые в голове, эти числа превращают ревью архитектуры в дешёвый отсев: дизайн, что читает с диска на запрос, делает синхронные межрегиональные вызовы или стреляет N+1 запросами, умирает в одном предложении — без всякого бенчмарка. Теперь, когда на ревью кто-то скажет «это всего один лишний вызов», ты за пять секунд поймёшь: 0,5 мс или 150 мс — и выживает ли дизайн с такой ценой.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.