Аппаратные счётчики и Intel TMA: диагностика подкатегорий
Аппаратные счётчики производительности отличают compute-bound от memory-bound, когда оба выглядят одинаково широкими. Фреймворк Intel TMA привязывает каждый такт CPU к конкретному микроархитектурному ресурсу.
Flame graph называет горячую функцию. Два инженера спорят: один говорит «перепишем алгоритм», другой — «исправим раскладку памяти». На уровне flame graph оба фрейма выглядят одинаково. Запуск perf stat -e instructions,cycles,cache-misses против функции решает спор за 30 секунд: IPC 0.4, cache-miss rate 18%. Побеждает раскладка памяти. Изменение алгоритма потратило бы спринт впустую.
Аппаратные счётчики: второй проход
Flame graph называет функцию. Аппаратные счётчики производительности показывают, что функция делала внутри CPU. perf stat -e cycles,instructions,cache-misses,branch-misses на том же горячем листе даёт IPC, miss rate и типы stall.
- Широкий фрейм с IPC 3.0: compute-bound. CPU выполняет алгоритм. Семейство исправлений: алгоритм, SIMD, специализация.
- Широкий фрейм с IPC 0.4 и cache-miss rate 15%: memory-bound. CPU ждёт RAM. Семейство исправлений: изменение раскладки данных.
На flame graph одинаковая ширина — противоположные исправления. Аппаратные счётчики — это второй диагностический проход, предотвращающий оптимизацию не тем инструментом на нетривиальных горячих путях.
| Показания счётчиков | Категория | Семейство исправлений |
|---|---|---|
| IPC 2–4, низкий cache-miss rate | Compute-bound (CPU-bound) | Лучший алгоритм, векторизация (SIMD) |
| IPC <1, высокий cache-miss rate | Memory-bound (cache-bound) | Раскладка данных (SoA, непрерывная), порядок обхода |
| Высокий branch-miss rate | Bad speculation | Устранение ветвлений, branchless-код, сортировка входных данных |
| Высокий stall cycles, низкий instructions | Front-end bound (выборка/декодирование инструкций) | Уменьшение размера кода, оптимизация instruction cache |
Intel TMA: строгая таксономия
Когда случай, где «compute или memory?» неочевиден по одному IPC — или когда SLO требует абсолютной уверенности перед спринтом реструктуризации — нужен инструмент точнее модели пяти форм.
Модель пяти форм — рабочее приближение. Строгая версия — Intel Top-Down Microarchitecture Analysis (TMA), формализованная в Intel Optimization Manual и доступная через VTune, Linux perf (через toplev.py) и аналог AMD uProf.
TMA классифицирует каждый такт CPU в четыре верхнеуровневых корзины:
- Retiring (~25–50% на оптимизированном коде): реальная работа — CPU выполнял полезные инструкции.
- Bad Speculation (~5–15%): промах предсказателя ветвлений — конвейер сброшен, инструкции отброшены.
- Front-End Bound (~5–15%): stall выборки или декодирования инструкций — CPU не успевает заполнять конвейер новыми инструкциями.
- Back-End Bound (~30–60% на типичных нагрузках): stall памяти или вычислительных ресурсов.
Back-End Bound делится дальше:
- Memory Bound → L1 Bound, L2 Bound, L3 Bound, DRAM Bound, Store Bound
- Core Bound (вычислительные порты, цепочки зависимостей, делители с большой латентностью)
Каскад точно указывает, на каком ресурсе CPU голодает на горячем пути:
- DRAM-bound → исправление раскладки данных
- Bad Speculation → устранение ветвлений
- Front-End Bound → уменьшение размера кода
- Core Bound → настоящее алгоритмическое переосмысление или SIMD
Для senior performance-работы на критических сервисах TMA — диагностика с наивысшим разрешением. Команды, поставляющие latency-sensitive инфраструктуру (HFT, database engines, kernel hot paths), считают его стандартом.
▸Почему это работает
Скрипт Linux toplev.py реализует TMA с помощью perf-событий на любом современном процессоре Intel. Он автоматически обходит дерево TMA и выводит, какая корзина доминирует. Типичный вызов: toplev.py --core S0-C0 -l2 sleep 5. Вывод напрямую соответствует четырём корзинам и подкорзинам и называет, какой аппаратный ресурс является узким местом.
Читать вывод аппаратных счётчиков для диагностики memory-bound пути
# perf stat -e cycles,instructions,cache-misses,LLC-load-misses ./service --bench feed-rank
8,400,000,000 cycles
3,360,000,000 instructions # 0.40 insns per cycle (IPC)
900,000,000 cache-misses # 10.7% of all memory refs
700,000,000 LLC-load-misses # 78% of cache misses miss L3 too
# Горячая функция из flame graph: score_embeddings()
# Self-time: 42% CPU
# IPC: 0.40 ← CPU простаивал 60% времени
# L3 miss rate: очень высокий — почти каждый запрос идёт в DRAM IPC 0.40 и 78% промахов кеша достигают DRAM. Какая это корзина TMA и на какое семейство исправлений она указывает?
Горячий leaf — JSON-сериализация при 28% CPU. У команды четыре варианта. Выберите senior-выбор.
Где формализован строгий фреймворк Top-Down Microarchitecture Analysis (TMA) — Retiring / Bad Speculation / Front-End Bound / Back-End Bound — и какой инструмент предоставляет его напрямую?
Горячий путь показал функцию X при 25% CPU. После исправления она упала до 5%. Общий CPU% остался прежним. Каково наиболее вероятное системное объяснение?
- 01Когда нужно обращаться к аппаратным счётчикам вместо простого чтения flame graph, и что они показывают того, чего flame graph не может?
- 02Опишите четырёхкорзинный каскад TMA и исправление, на которое указывает каждая корзина.
Аппаратные счётчики производительности — это второй диагностический проход, отличающий compute-bound от memory-bound горячих путей, когда оба выглядят одинаково на flame graph. IPC ниже 1 с высоким L3 miss rate указывает на исправления раскладки данных; IPC 2–4 с низким miss rate — на алгоритмические исправления. Фреймворк Intel TMA каскадируется от четырёх верхнеуровневых корзин до конкретных подресурсов (L1-bound, DRAM-bound, core-bound), давая наиболее точную диагностику из доступных. Для latency-sensitive production-сервисов запуск perf stat или VTune на неоднозначных горячих листах является стандартной практикой перед тем, как тратить инженерное время на исправление. Теперь, когда команда спорит «алгоритм или раскладка?», ты запустишь perf stat первым — тридцать секунд счётчиков заменяют тридцать минут дебатов.
Практика
Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.
встречается в162
- Путь запроса: семь остановок от сокета до ответаjunior
- Accept и парсинг: от очереди ядра до типизированного запросаmiddle
- Маршрутизация и middleware: что выполняется и в каком порядкеmiddle
- Обработчик и ответ: от бизнес-логики до байтов на проводеmiddle
- Стриминг и backpressure: когда клиент читает медленнее, чем вы пишетеsenior
- Таймауты и хвостовая задержка: бюджеты, дедлайны и ловушка fan-outsenior
- Middleware и DI: два паттерна, формирующие любой backendjunior
- Пишем middleware: сигнатуры, next() и три модели фреймворковmiddle
- Инверсия управления: как зависимости добираются до классаmiddle
- Скоупы и время жизни DI: singleton, request, transientmiddle
- DI как шов для тестов: фейки, моки и граница, которая важнаsenior
- DI-контейнеры в продакшене: графы разрешения, циклы и когда не стоитsenior
- Блокирующий vs неблокирующий I/O: два способа ждатьjunior
- Event loop: один поток, упорядоченные фазыmiddle
- Что блокирует цикл: CPU-работа и синхронные вызовыmiddle
- Вынос CPU-работы: worker threads и пул libuvmiddle
- Backpressure и ограниченная конкурентностьsenior
- Пропускная способность под нагрузкой: хвостовая задержка и насыщениеsenior
- Зачем пул: цена создания соединенияjunior
- Размер пула: почему больше не значит быстрееmiddle
- Взятие и таймауты: очередь ожидания — настоящий дроссель задержкиmiddle
- Стратегии retry: backoff, jitter и thundering herdmiddle
- Наблюдаемость, production-инциденты и дизайн для глобального масштабаsenior
- Задачи, микрозадачи и scheduler.yield()middle
- Точность таймеров, троттлинг и фоновая работаmiddle
- Event loop Node.js: фазы, nextTick и задержка циклаsenior
- Стратегии рендеринга: SSG, SSR, ISR, streaming и гидратацияjunior
- SSG, SSR, ISR, streaming и RSC — как работает каждая стратегияmiddle
- Цена гидратации: selective, progressive, острова, resumabilitymiddle
- Core Web Vitals: что измеряют LCP, INP и CLSjunior
- LCP: четыре фазы, одна доминирующая стоимостьmiddle
- INP: input delay, processing, presentationmiddle
- Lab vs field: почему они расходятся и как использовать каждыйmiddle
- Трейдоффы метрик, RUM-атрибуция и цикл CI+полеsenior
- Общая картина: от URL до LCP до INP как эстафетаjunior
- Восемь слоёв трассировки: от service worker до второй навигацииmiddle
- Пять канонических поломок: где производство стабильно ломаетсяsenior
- Метод трёх треков: чтение трасс и построение системы мониторингаsenior
- Что такое индекс и как он ускоряет запросыjunior
- Leading-column rule: почему порядок столбцов в composite-индексе важенmiddle
- Partial, expression и covering-индексыmiddle
- Типы индексов: GIN, GiST, BRIN, Hash, Bloom и HOT-обновленияmiddle
- Index-only scan, Visibility Map и INCLUDEsenior
- Типичные сбои в продакшне и аудит индексовsenior
- Упражнение по проектированию индексов: стратегия полнотекстового поискаsenior
- EXPLAIN и планы выполнения: что решает планировщик и почемуjunior
- Типы сканирования: Seq, Index, Bitmap, Index-Onlymiddle
- Алгоритмы соединения и каскад ошибок оценки строкmiddle
- pg_statistic, ANALYZE и производственная наблюдаемостьmiddle
- Расширенная статистика: исправление ошибок оценки для коррелированных колонокsenior
- Кеш планов, настройка константных стоимостей и внутренности планировщикаsenior
- Производственные режимы отказа и стабильность плановsenior
- Connection pool: зачем амортизировать стоимость backend Postgresjunior
- Режимы PgBouncer: session, transaction и statementmiddle
- Размер пула: формула (ядра × 2) + шпинделей и двухуровневый стекmiddle
- Исчерпание пула и idle-in-transaction: сценарий отказа в 3 ночиmiddle
- Миграция на transaction mode: план развёртывания и prepared statements в PgBouncer 1.21middle
- Процессная модель Postgres и почему увеличение max_connections снижает производительностьsenior
- Ландшафт пулеров 2026, serverless connection storms и полная таксономия отказовsenior
- ADD COLUMN: мгновенно в PG 11+ против перезаписи в старом Postgresjunior
- Режим отказа очереди блокировок: почему мгновенный DDL может заморозить базуmiddle
- Безопасные DDL-паттерны: NOT VALID, CONCURRENTLY и исправления небезопасных операцийmiddle
- Таксономия сбоев миграций и дисциплина продакшнаsenior
- Выбор ключа шарда: стратегии hash, range, list и directorymiddle
- Ко-локация и Citus: инвариант, делающий шардирование пригодным к использованиюmiddle
- Режим отказа hot shard: обнаружение, изоляция и долгосрочная политикаmiddle
- Онлайн-решардинг, 2PC и операционная стоимость шардированияsenior
- Семь актов: от CREATE TABLE до Citusjunior
- Акты 1–3 в глубину: схема, индексы и статистика планировщикаmiddle
- Акты 4–6 в глубину: MVCC bloat, connection pooling и безопасные миграцииmiddle
- Акт 7 в глубину: шардинг, co-location и семиуровневый каскад трейдоффовmiddle
- Наблюдаемость, антипаттерны и производственный триажsenior
- Поколенческий GC и Scavengermiddle
- Major GC: mark, sweep, compactsenior
- Write barriers: цена инкрементального и поколенческого GCsenior
- Биты в проводеjunior
- Математика задержкиmiddle
- Bufferbloat и перегрузкаsenior
- Граница физического уровняsenior
- Номера последовательности и состояние соединенияmiddle
- Управление потоком и перегрузкойmiddle
- BBR, производственная наблюдаемость и за пределами TCPsenior
- CDN: контент по соседствуjunior
- Anycast и GeoDNS: маршрутизация к ближайшему edgemiddle
- Многоуровневый кеш и Cache-Controlmiddle
- Заголовок Vary и cache keysmiddle
- Stale-while-revalidate и cache stampedesenior
- Edge workers и edge-side compositionsenior
- CDN: операции и observabilitysenior
- WebSocket: HTTP-апгрейд до постоянного соединенияjunior
- WebSocket vs SSE vs long-polling: выбор правильного транспортаmiddle
- Backpressure в WebSocket: когда клиенты не успеваютmiddle
- Реконнект: jittered backoff, thundering herd, восстановление сообщенийsenior
- WebSocket в масштабе: HTTP/2 мультиплексирование, permessage-deflate, C10Msenior
- WebSocket в production: прокси, безопасность и распределённая архитектураsenior
- Что делают обратные проксиjunior
- Алгоритмы балансировки: от round-robin до power-of-two-choicesmiddle
- L4 vs L7 балансировка и сохранение IP клиентаmiddle
- Health checks, connection draining и slow startmiddle
- Retry-бури, circuit breakers и load sheddingsenior
- Устойчивая архитектура LB: anycast, zone-aware маршрутизация и observabilitysenior
- Почему QUIC, а не TCP+TLSjunior
- QUIC-потоки и head-of-line blockingjunior
- Объединённое рукопожатие и 1-RTTmiddle
- Connection ID и миграция сетиmiddle
- Обнаружение потерь и управление перегрузкойmiddle
- Возобновление 0-RTT и шифрование пакетовsenior
- Развёртывание и стоимость CPUsenior
- DDoS: что это и почему работаетjunior
- Атаки усиления и истощение состоянияmiddle
- Ограничение скорости: алгоритмы и архитектураmiddle
- WAF, межсетевые экраны, mTLS и HSTSmiddle
- Отравление DNS-кэша и BGP-перехватsenior
- Эшелонированная защита и экономика атакsenior
- Двенадцать слоёв: один URL, семь действующих лицjunior
- DNS, TCP, TLS по очереди: куда уходят миллисекундыmiddle
- Критический путь рендеринга и Core Web Vitalsmiddle
- Перехват прокси и шлюзы безопасности: rate limiter, WAF, mTLSmiddle
- Альтернативные пути: QUIC 0-RTT, WebSocket upgrade, миграция соединенияmiddle
- Наблюдаемость: распределённые трейсы, USE/RED и семплированиеsenior
- Устойчивость: каскадные повторы, circuit breakers и error budgetsenior
- Что такое три сигнала: метрики, логи, трейсыjunior
- Метрики и cardinality: cost-модель time-series databasemiddle
- Логи и объём: cost-модель структурного логированияmiddle
- Трейсы и сэмплирование: cost-модель distributed tracingmiddle
- Join-ключи и exemplar''''ы: как три сигнала становятся компонуемымиmiddle
- Observability 2.0: широкие события и сдвиг стоимостиsenior
- Режимы сбоя и инженерная практика: cardinality budget''''ы, PII и сэмплированиеsenior
- Зачем нужны структурные логи: дневник против таблицыjunior
- Схема продакшн-лога: поля, которые несёт каждая строкаmiddle
- Log levels и маршрутизация алертовmiddle
- Стратегии sampling и стоимость логовmiddle
- PII-редакция и log injectionsenior
- Propagation trace-контекста в логахsenior
- OTel Logs Data Model и audit-логи как подсистемаsenior
- Сигналы OTel, Semantic Conventions и проводной формат OTLPmiddle
- Авто-инструментирование и ручные спаны: правило 80/20 в OTelmiddle
- Collector OTel: receivers, processors, exporters и паттерны развёртыванияmiddle
- Стратегии сэмплирования: head, tail и parent-basedmiddle
- Vendor-нейтральность, eBPF-инструментирование, Operator и OTel в браузере и serverlesssenior
- Эксплуатация OTel Collector: надёжность, version skew, режимы отказа и управлениеsenior
- RED и USE: два чек-листа, одна дисциплина триажаjunior
- Инструментация RED в Prometheus: счётчики, гистограммы и дисциплина cardinalitymiddle
- USE на Linux: CPU, память, диск, сеть и PSImiddle
- Golden signals, структура дашборда и auto-RED в service meshmiddle
- Cardinality как драйвер затрат: label, PII, exemplars и семплированиеmiddle
- Native histograms, SLO и паттерны production-сбоевmiddle
- Выбор SLI и SLO-целей: отношения, не ощущенияmiddle
- Multi-window multi-burn-rate-алертинг: почему AND лучше ORmiddle
- Error budget policy, latency SLO и составные journeysmiddle
- Iceberg SLI, математика составного SLO и SLA vs SLOsenior
- Flame graph: читаем картинку, которая показывает, куда ушло времяjunior
- Sampling vs instrumentation profiling: почему 99 Гц побеждает в productionmiddle
- Типы профилей: CPU, память, off-CPU, mutex — какой когда братьmiddle
- Continuous profiling: always-on flame graphs с eBPF и корреляцией trace-idmiddle
- Как flame graph строится из сэмплов и как использовать его в productionmiddle
- Linux perf, внутренности eBPF, PGO и ограничения sampling''''аsenior
- Profiling в production: безопасность, war stories, OTel profiles и дизайн инфраструктурыsenior
- Debugging-воронка: SLO → RED → trace → profilejunior
- Архитектура OTel: один SDK, четыре сигнала, один wire-форматmiddle
- Экономия на observability: удерживаем затраты в пределах 5% inframiddle
- Масштаб, безопасность и ROI наблюдаемых системsenior
Что-то непонятно?
Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.