ПроКодинг - Откроем для вас мир IT!

Короткий ответ: на C++ пишут всё, где важны скорость, предсказуемая задержка и полный контроль над железом. Давайте пройдёмся по реальным областям и сразу добавим инструменты, чтобы у вас была карта действий, а не просто список.

Системное ПО. Части ОС и драйверов чаще пишут на C, но сервисы, файловые подсистемы, браузерные движки и рендереры - на C++. Примеры: Blink в Chromium, Gecko у Firefox (вместе с Rust), графическая библиотека Skia, медиастеков - тонна C++. Советы: RAII и умные указатели вместо ручного free, включайте Address/UB/ThreadSanitizer, гоняйте статический анализ (clang-tidy), и меряйте, а не «ощущайте» производительность (perf, ETW).

Игры и движки. Unreal Engine 5 - C++. Большинство AAA-игр и игровых инструментов - C++. Низкоуровневый рендер (DirectX/Vulkan/Metal), физика, анимация, стриминг ресурсов - всё на нём. Что учить: ECS-подход (например, EnTT), математику для 3D (glm), профилировщики кадров (RenderDoc, PIX), корутины C++20 для асинхронной загрузки, кэш-дружелюбные структуры данных.

Высоконагруженные серверы и финтех. Биржевые шлюзы, HFT, брокеры сообщений, базы - это про C++. Примеры: ClickHouse, RocksDB, часть MongoDB, компоненты TensorFlow/PyTorch (LibTorch/ATen) - C++. Ключевые приёмы: измеряйте p99/p999, избегайте лишних аллокаций (арены, small buffer optimization), используйте io_uring/uring-готовые обёртки на Linux, Asio/Boost.Asio для сетевого стека, folly/abseil для утилит.

Встраиваемые и реальное время. Микроконтроллеры, робототехника, автопилоты, аудиообработка - C++ популярен за счёт нулевых абстракций. Практика: ограниченный профиль C++14/17 (без исключений и RTTI, если RT-ограничения жёсткие), статическое выделение памяти, внимательная работа с прерываниями. Инструменты: Zephyr/FreeRTOS, CMake, unit-тесты на стенде (doctest/Catch2), профилировка на железе.

HPC и ML-инфраструктура. GPU-ядра - CUDA C++, SYCL/oneAPI набирает обороты, многопоток - OpenMP/TBB. Линейная алгебра: Eigen, cuBLAS/MKL. Частый паттерн: горячий код на C++, фронт - на Python. Связка - pybind11. Совет: храните данные в непрерывной памяти, избегайте виртуальности в горячих циклах, считайте cache miss и branch mispredict.

Когда выбирать C++? Берите, если вам нужна минимальная задержка, контроль над памятью, доступ к SIMD/GPU и детерминизм. Если важнее безопасность по умолчанию - смотрите на Rust; если скорость разработки и простая сетка - Go. На практике языки часто смешивают: критичное - C++, остальное - на том, что ускоряет команду.

Быстрый старт по стеку. Компиляторы: GCC/Clang/MSVC, стандарт C++20/23 (модули уже живут, но интеграция в сборку всё ещё непроста). Сборка: CMake, пакеты: vcpkg или Conan. Качество: clang-tidy, sanitizers, cppcheck, fuzzing (libFuzzer/AFL++). Тесты: GoogleTest/Catch2, бенчмарки: Google Benchmark. Логи: spdlog, форматирование: fmt, HTTP/gRPC: cpp-httplib/Boost.Beast/gRPC.

Где C++ незаменим

Если вам нужна минимальная задержка, прямой доступ к памяти и железу, предсказуемость под нагрузкой - берут C++. Это видно по конкретным продуктам, которые крутятся у всех на глазах и в продакшене годами.

Браузеры и графические движки. Рендер ядра Chromium (Blink), движок Gecko у Firefox (часть модулей переписаны на Rust, но основной рендер и инфраструктура держатся на C++), библиотека отрисовки Skia и JS-движок V8 - всё это на C++. Причина простая: миллионы строк кода должны работать в 16,6 мс на кадр (60 FPS) и ужимать память на десятках платформ.

Игровые движки и 3D. Unreal Engine 5 почти весь на C++. Большинство AAA-игр держат геймплейный слой на скриптах, но горячие подсистемы - рендер (DirectX/Vulkan/Metal), физика, стриминг ресурсов - на C++. Тут важны 8,3-16,6 мс на кадр и стабильный фреймтайм без «спайков».

Медиа и реальное время. WebRTC (ядро Google) - это C++: jitter-буферы, A/V синхронизация, сетевые стеки. Кодеки: x265 - C++ (x264 - C). Видеозвонки обычно целят end-to-end задержку до ~150-200 мс, а обработка каждого аудиофрейма - десятки миллисекунд и меньше.

Финтех и низкие задержки. Биржевые шлюзы, HFT, risk-движки - C++ для микросекундных задержек и отсутствия GC-пауз. Типично стремятся к p99 ниже миллисекунды, а «тик‑ту‑трейд» - десятки микросекунд. Часто используют kernel-bypass стеки (DPDK/AF_XDP), lock-free структуры и аккуратное NUMA‑распределение.

Хранилища и базы. ClickHouse - C++, RocksDB - C++, части MySQL - C/C++. Тут упор на пропускную способность и эффективные IO‑пути: последовательные сканы, сжатие, кэш‑слои. В реальных кейсах ClickHouse обрабатывает миллиарды строк на запрос, а RocksDB при правильной настройке даёт сотни тысяч-миллоны операций в секунду на NVMe.

HPC и GPU. CUDA - это расширение C++, SYCL/oneAPI - современная альтернатива с переносимостью. Библиотеки вроде TBB, Eigen, cuBLAS/MKL - де-факто стандарт. Здесь считают не «быстро/медленно», а выполнение относительно пиков FLOPS и пропускной памяти, плюс эффективность кэшей.

Встраиваемые и робототехника. Микроконтроллеры часто имеют 64-512 КБ RAM и несколько мегабайт флеша. C++ в «урезанном» профиле (без исключений/RTTI) даёт нулевые абстракции и контроль ISR‑латентности. ROS 2 (ядро - C++) - в промышленных роботах и автономке.

  • Нужна жёсткая латентность и предсказуемость? Думайте о без-аллоцирующем пути, аренах, предвыделении и pinning потоков к ядрам.
  • Сильная графика/мультимедиа? Инвестируйте в профилировщики кадров и кэш-дружелюбные структуры (SoA/ECS).
  • Сетевой высоконагруженный бэкенд? Следите за p99/p999, используйте неблокирующий IO (io_uring/epoll) и пулы соединений.
  • Встроенные? Отключайте исключения, используйте статическую память, держите ISR короткими, проверяйте регистры и барьеры памяти.
ОбластьПримерыПочему выбираютТипичные метрики/целевые цифры
Браузеры/рендерChromium Blink, V8, Skia, Firefox GeckoСкорость, переносимость, тонкий контроль памяти60-120 FPS (16,6-8,3 мс/кадр), низкий расход RAM
Игры/движкиUnreal Engine 5, Frostbite (EA), RE Engine (Capcom)Детерминизм, производительность на консолях/PCСтабильный фреймтайм, быстрый старт уровня (<1-2 с)
Медиа/RTCWebRTC, x265, OBS плагиныРеальное время без GC-паузEnd-to-end видео ≤150-200 мс, аудио буферы 10-20 мс
Финтех/HFTБиржевые шлюзы, маркет-мейкингМикросекундные задержки, zero-copy путиp99 <1 мс, тик‑ту‑трейд 10-100 мкс
Базы/хранилищаClickHouse, RocksDB, MySQL (части)IO‑эффективность, контроль аллокацийСотни тыс.-млн ops/s на NVMe, сканы млрд строк/запрос
HPC/GPUCUDA, SYCL/oneAPI, TBB, EigenДоступ к SIMD/GPU, нулевые абстракцииМакс. близко к пику FLOPS, высокое L1/L2 hit‑rate
Встраиваемые/RTROS 2, FreeRTOS/Zephyr приложенияМалая память, жёсткий тайминг ISRRAM 64-512 КБ, ISR десятки мкс

Практические приёмы, которые окупаются в этих зонах: включайте Sanitizers (ASan/TSan/UBSan) в CI, используйте профилировку (perf/VTune, RenderDoc/PIX), измеряйте холодный и тёплый старт отдельно, пробуйте аллокаторы jemalloc/tcmalloc и арену под «горячие» пути, держите бинарники с PGO/LTO для продакшена.

Игры и графика

Язык C++ - это то, на чём работают ядра основных игровых движков и графических подсистем. Unreal Engine 5, Unity (ядро рантайма), Frostbite, id Tech, Godot (сердце движка) - все опираются на C++ ради скорости, прямого доступа к памяти и предсказуемых задержек.

“Unreal Engine source code is written in C++ and available on GitHub.” - Epic Games, Unreal Engine documentation

Как это выглядит на практике. Высокоуровневую логику дизайнеры и геймдизайнеры собирают в Blueprints (UE) или на C# (Unity), а тяжёлые части - рендер, физика, анимация, стриминг ресурсов - пишутся и профилируются на C++. В Unity многие студии выносят горячие участки в нативные плагины; на консолях часто включают IL2CPP, который переводит C# IL в C++ для производительности.

Графический стек в играх чаще всего строится на Direct3D 12 (Windows/Xbox), Vulkan (кроссплатформа, включая Android, Steam Deck) и Metal (Apple). Эти API дают тонкий контроль над командными списками, памятью и синхронизацией GPU. Такой контроль нужен, чтобы держать стабильный кадр и не ловить микрофризы из‑за скрытых аллокаций или лишних синхро-точек.

Цель по FPSБюджет кадра (мс)Где это важно
3033.33Кинематографичность, слабое железо
6016.67База для ПК/консолей
9011.11VR (часто целятся в 90+)
1208.33Мониторы 120 Гц, next‑gen консоли
1446.94Соревновательные шутеры на ПК
2404.17Киберспорт, топовое железо

Отсюда вытекают приёмы. Данные держим кэш‑дружелюбно: массив структур заменяем на структуры массивов, горячие поля - рядом. В геймплее и анимации помогает ECS (например, EnTT) и job‑системы, чтобы грузить все ядра. Для стриминга текстур/моделей удобно использовать корутины C++20: меньше самописных статемашин и понятный жизненный цикл.

Инструменты без которых никуда: RenderDoc для графических кадров, PIX (D3D12) на Windows и Xbox, NVIDIA Nsight и AMD Radeon GPU Profiler для GPU; Tracy и Remotery - для CPU‑профайлинга и фрейм‑таймлайнов. Эти тулзы показывают, где вы теряете миллисекунды: лишние барьеры, перебросы памяти, многократные компиляции шейдеров на горячем пути.

Про шейдеры. На ПК и консолях исходники обычно на HLSL; через DXC их можно собирать и в SPIR‑V для Vulkan. Кэшируйте результаты компиляции, заранее «варите» варианты (PSO) для популярных материалов и световых наборов, чтобы избежать фризов при первом появлении эффекта.

Память и загрузка контента - главный источник лагов. Текстура 4K RGBA8 без сжатия - около 33 МБ только на нулевом мипе; вся мип‑цепочка добавит ещё ~33%. Поэтому в продакшене почти всегда используют BC‑сжатие (BC1/BC3/BC7) и стриминг мипов по расстоянию до камеры. На мобильных - ETC2/ASTC.

Пять шагов, чтобы быстро собрать прототип рендера и не увязнуть:

  1. Соберите окружение: CMake + компилятор (Clang/GCC/MSVC), заведите vcpkg или Conan для зависимостей.
  2. Создайте окно и контекст: GLFW/SDL2 + backend (D3D12/Vulkan/Metal).
  3. Сделайте минимальный пайплайн: загрузите шейдеры, подготовьте вершинный буфер, отрендерьте треугольник. Сразу подключите RenderDoc.
  4. Добавьте систему ресурсов: ассет‑пак, отдельный поток ввода‑вывода, декодер текстур (stb_image) и фоновые загрузки (корутины).
  5. Поставьте метрики: средний и p99 по кадру, счётчики аллокаций, число draw/dispatch. Зафиксируйте цель (например, 16.67 мс) и защищайте её ревью.

Полезные библиотеки: glm (математика), EnTT (ECS), spdlog + fmt (логи), meshoptimizer (компрессия и ремешинг), shaderc/DXC (компиляция шейдеров), SPIRV‑Cross (трансляция шейдеров), tinygltf/Assimp (модели). Всё это экономит недели рутины.

Про платформы. На консолях (PS, Xbox, Nintendo) студии собирают нативные билды, профилируют на девкитах и следят за жёсткими лимитами по памяти и потокам ввода‑вывода. На iOS/Android - разные драйвера и ограничения по шейдерам, поэтому автоматические тесты на реальных устройствах обязательны.

И короткая проверка на здравый смысл для любой фичи: можно ли отложить работу? можно ли сделать её асинхронной? можно ли уменьшить данные? можно ли переиспользовать кэш? Эти четыре вопроса часто возвращают потерянные миллисекунды без «магии».

Серверы, базы и финтех

Серверы, базы и финтех

Задачи тут простые по формулировке и жёсткие по требованиям: минимум задержки, максимум пропускной способности, стабильный p99/p999. Именно поэтому так часто выбирают C++: прямой контроль над памятью, предсказуемость, SIMD и доступ к системе без лишних прослоек.

Живые примеры. ClickHouse - колонночная СУБД, открыта в 2016, написана на C++; в ней векторное исполнение и активное использование SIMD (SSE/AVX), сжатие LZ4/ZSTD и собственный ClickHouse Keeper (Raft) для координации. RocksDB - библиотека key-value от Facebook (2013), C++, LSM-дерево; широко используется в Kafka Streams, TiKV и Flink как долговременное состояние. MongoDB - серверная часть на C++, основной движок хранения сейчас WiredTiger (интегрирован, написан на C). ScyllaDB - переписанный «Cassandra-совместимый» движок на C++/Seastar (thread-per-core, shared-nothing), показывает миллионы операций в секунду на узел. Envoy - L7‑прокси от Lyft, C++, стандарт де-факто в сервис‑мешах (Istio). gRPC имеет полноценную C++‑обвязку поверх C‑ядра и хорош для внутренних RPC.

Финтех. Биржевые шлюзы, risk‑сервисы, ценообразование, маршрутизация ордеров. Протоколы: FIX 4.2/4.4 и FAST/SBE; для FIX есть QuickFIX (C++), для SBE - кодогенераторы от FIX Trading Community. В низкой задержке часто встречается kernel bypass (DPDK, OpenOnload), NUMA‑пиннинг потоков, предвыделение памяти, отказ от исключений и RTTI в «горячем» коде, упор на lock‑free очереди (например, moodycamel ConcurrentQueue) и аренаторы памяти.

Сетевой стек и асинхронщина. Классика - epoll/kqueue/IOCP + Boost.Asio или standalone Asio. На Linux всё чаще используют io_uring (ядро 5.1+): меньше системных вызовов, батчинг, SQPOLL снижает переключения контекста. Для межсервисного общения - gRPC, для лёгких HTTP - Boost.Beast или cpp-httplib. Для брокеров сообщений из мира C++ стоит посмотреть на Redpanda (Kafka‑совместимый, C++/Seastar) - без JVM и с предсказуемой задержкой.

Хранение данных. Встраиваемые движки: LevelDB (C++), RocksDB (C++). Для сериализации и экономии CPU/памяти: FlatBuffers и Cap'n Proto (zero-copy), Protobuf - как «золотая середина». В продакшене базы на C++ часто комбинируют: OLAP‑аналитика в ClickHouse, key‑value низкого уровня - RocksDB, кеш на стороне сервиса - собственные структуры + jemalloc/tcmalloc.

Производительность и стабильность. Смотрите на p50/p95/p99/p999, хвосты важнее среднего. Собирайте LTO/PGO, избегайте лишних аллокаций (арены, small buffer optimization), держите данные в непрерывной памяти, в критических циклах исключайте виртуальные вызовы. Инструменты: perf, FlameGraph, heaptrack, sanitizers (ASan/TSan/UBSan), статанализ (clang-tidy), профилировщики сетевого стека (bcc/eBPF).

ПроектГодЯдро/языкКласс задачиПодтверждённый факт
ClickHouse2016C++OLAP СУБДКолонночная, SIMD-векторизация, ZSTD/LZ4; собственный ClickHouse Keeper на Raft
RocksDB2013C++KV (LSM)Используется в Kafka Streams, TiKV, Flink как state backend
MongoDB (Core)2009C++Документная СУБДДвижок хранения WiredTiger интегрирован; серверная часть написана на C++
ScyllaDB2015C++/SeastarWide-columnThread-per-core, shared-nothing; миллионы ops/sec на узел
Envoy2016C++L7-проксиШироко используется в Istio как data plane
Redpanda2020C++/SeastarБрокер событийСовместим с Kafka API, без JVM, ориентирован на низкую задержку
gRPC C++2015C/C++RPCC++-клиент и сервер поверх C-core, поддержка HTTP/2
QuickFIX2001C++FIX протоколОткрытая реализация FIX 4.x, используется в торговых шлюзах

Архитектурные приёмы, которые работают на практике:

  • Thread-per-core (Seastar‑подход): без общей памяти между ядрами, обмен - через очереди/шардинг.
  • SO_REUSEPORT и шардирование по CPU для входящих соединений.
  • Предвыделение и аренаторы (Boost.Pool, monotonic_resource из pmr) вместо «new/delete» в горячем пути.
  • Zero-copy: splice/sendfile на Linux, mmap для больших файлов; на RPC - FlatBuffers/Cap'n Proto.
  • Хвосты латентности: сохраняйте гистограммы (HdrHistogram), а не только среднее.

Мини‑чек‑лист для p99 в проде:

  1. Зафиксируйте частоту CPU и энергосхему (performance), привяжите потоки к ядрам и учтите NUMA.
  2. Сначала профилируйте (perf + FlameGraph), потом оптимизируйте «верхние» 20% горячих мест.
  3. Соберите с sanitizers и включите clang-tidy в CI - ловите undefined behavior до релиза.
  4. Измеряйте на боеподобной нагрузке: реальный размер сообщений, реальные шаблоны запросов.
  5. Следите за p999 и паузами GC… если завели JVM‑соседей; в чистом C++ - за аллокатором и page faults.

Когда это всё уместно? Там, где микросекунды стоят денег: матчинги ордеров, риск‑лимиты в онлайне, брокеры с тысячами топиков и миллионами сообщений в секунду, OLAP‑запросы по десяткам терабайт. Если требования мягче - часто выгодно вынести критичную часть на C++, а остальное собрать на языках быстрее в разработке.

Встраиваемые и реальное время

Когда у устройства есть жёсткие дедлайны - мотор надо обновлять каждые 50 мкс, аудио - без щелчков, лидара - без пропусков - язык выбирают прагматично. C++ здесь популярен, потому что даёт нулевые абстракции, контроль над памятью и предсказуемое время выполнения. Примеры: автопилоты дронов, контроллеры BLDC‑моторов, медицинские приборы, аудио DSP, промышленные ПЛК.

Два пути: bare‑metal (без ОС) или лёгкая RTOS. Без ОС - минимум накладных расходов и полный контроль. RTOS нужна, когда много периферии и параллельных задач. Классика: FreeRTOS (поддержка от Amazon, открытый код, куча портов), Zephyr (Linux Foundation, активно поддерживают Intel, Nordic, NXP, ST; сотни плат из коробки). Оба дают приоритетный планировщик с предвосхищающим вытеснением, очереди, семафоры и таймеры. Для суперточных задач используйте tickless‑режим и таймеры/прерывания вместо тикового таймера.

Про железо. На Cortex‑M NVIC обрабатывает прерывания с латентностью от ~12 тактов плюс задержки памяти; tail‑chaining ускоряет обработку цепочек IRQ. Приоритеты - чем меньше численное значение, тем выше приоритет; реально используются только старшие биты (типично 4). Для маскирования используйте BASEPRI, а не полное запрещение прерываний. DMA разгружает ядро: потоковые АЦП/USART/SPI лучше вести через двойной буфер и кольцевой буфер в памяти.

Шаблон для ISR: держите обработчик коротким и без блокировок - делегируйте «тяжёлую» работу задаче.

  1. В ISR: читаем/записываем регистры, кладём событие в кольцевой буфер или очередь, выходим.
  2. В задаче: обрабатываем пакеты, считаем контрольные суммы, шлём дальше.
  3. Для приоритетной обработки используйте уведомления задач (FreeRTOS direct to task notifications) - это дешевле, чем очереди.

Языковой профиль для реального времени. Исключения и RTTI часто отключают: -fno-exceptions, -fno-rtti. Динамическую память ограничивают: статические буферы, std::array, фиксированные пулы, custom allocator. Для экономии флеша - LTO и -ffunction-sections -fdata-sections + --gc-sections. На маленьких МК ставят newlib-nano и отключают локаль/float‑printf.

Полезные приёмы на языке. Используйте constexpr для инициализации таблиц и предвычислений. Предпочитайте неизменяемые данные и непрерывные структуры (SoA/крупные блоки) - это уменьшает cache miss даже на простых кэшах/тясом TCM. std::span помогает работать с буферами без копий. Не помечайте всё подряд volatile: это для MMIO и флагов, а не для синхронизации; берите std::atomic и барьеры памяти там, где реально есть конкуренция (на RTOS).

Синхронизация и инверсии приоритетов. Мьютексы с наследованием приоритета обязательны (в FreeRTOS есть). Для горячих путей - lock‑free SPSC‑очереди между ISR и задачей. Помните: выделение памяти в ISR запрещено; функции HAL внутри ISR используйте осторожно - они часто тяжелее, чем прямой доступ к регистрам.

Питание и время жизни от батареи. Включайте сон ядра и периферии, переходите на tickless, будите задачи по событиям (EXTI, RTC, DMA‑complete). Откажитесь от «пульсирующих» таймеров в пользу аппаратных. Меряйте ток, а не гадайте: Otii Arc, Nordic PPK2 показывают пики и среднее.

Коммуникации. Для UART/SPI/I2C - DMA + двойная буферизация. Для CAN - фильтры и приоритеты кадров, кольцевые буферы без копий. С TCP/UDP на малых МК - lwIP в raw‑API режиме, чтобы избежать лишних копий и блокировок. Проверяйте целостность пакетов (CRC32/CRC16), закладывайте тайм‑ауты и «state machine» вместо сложных коллбеков.

Безопасность и обновления. Secure boot грузчик MCUboot активно используют в Zephyr. Лёгкие криптобиблиотеки: mbedTLS, wolfSSL. На малых МК чаще берут кривые X25519/Ed25519 вместо RSA из‑за размера и скорости. Watchdog включайте всегда, делайте «last‑good» банковую схему прошивки и атомарное обновление.

Инструменты и отладка. Компиляторы: arm-none-eabi-gcc/Clang, коммерческие IAR и Keil дают хорошую оптимизацию для МК. Сборка: CMake с кросс‑toolchain, у Zephyr - west. Отладка: SWD/JTAG, OpenOCD или J-Link, аппаратный трасс: ITM/SWO, ETM; анализ - Percepio Tracealyzer (FreeRTOS), SEGGER SystemView. На Cortex‑M включайте DWT->CYCCNT и меряйте задержки в тактах; простой способ увидеть джиттер - дёргать GPIO и смотреть на логическом анализаторе.

Тестирование. Львиную долю логики тестируйте на хосте: GoogleTest/Doctest, property‑based (rapidcheck). Эмуляторы: Renode для Cortex‑M/RISC‑V, QEMU (частичная поддержка ряда плат). HIL обязателен для драйверов. Санитайзеры на целевом МК недоступны, но на хосте - must‑have: ASan/UBSan помогают поймать ошибки протоколов и парсеров до железа.

Стандарты и требования. В авто - ISO 26262, в авиа - DO‑178C, в медицине - IEC 62304. Код‑гайдлайны: MISRA C++:2023 и AUTOSAR C++14. Статический анализ - PVS‑Studio, Coverity, Cppcheck, clang-tidy. Включайте жёсткие предупреждения (-Wall -Wextra -Werror) и проверяйте map‑файл: размеры секций, выравнивание стека, запас для ISR.

Когда брать RTOS, а когда - нет? Если у вас одна‑две жёсткие петли (например, 20 кГц для FOC и 1 кГц для IMU‑слияния), проще и надёжнее - bare‑metal с кооперативным планированием и аппаратными таймерами. Как только появляются сети, файловые системы, несколько периферий и UI - RTOS окупается.

Инструменты и практические советы

Инструменты и практические советы

Базовый рабочий набор под C++: компиляторы GCC/Clang/MSVC, сборка через CMake+Ninja, менеджер пакетов (vcpkg или Conan 2), статический анализ (clang-tidy), форматирование (clang-format), и CI на GitHub Actions или GitLab CI. Это закрывает 90% рутины и даёт повторяемые сборки на Linux/Windows/macOS.

Компиляторы и флаги. На Linux/Unix включайте -Wall -Wextra -Wpedantic, по мере готовности добавляйте -Wconversion -Wshadow. В MSVC аналог - /W4. Делать -Werror стоит в ветке CI, а локально - по желанию, иначе мешает экспериментов. Для профилирования держите фрейм-пойнтеры: -fno-omit-frame-pointer (GCC/Clang), в MSVC - по умолчанию OK в Debug. Оптимизации: Debug - -O0 -g, Release - -O3 -DNDEBUG (или -O2, если важнее время компиляции), профили - -g -O2.

Санитайзеры. AddressSanitizer и UndefinedBehaviorSanitizer ловят use-after-free, выходы за границы и UB; типичный оверхед - ~2x по времени и ~2x по памяти, зато находят ошибки рано. ThreadSanitizer - для гонок, оверхед ощутимый (иногда 5-15x), запускайте ночами в CI. На Linux это просто: -fsanitize=address,undefined и -fno-omit-frame-pointer; на macOS ASan/UBSan тоже доступны в Clang; на Windows - через Clang-cl или MSVC (ASan поддерживается в последних версиях VS 2022).

Статический анализ. clang-tidy с профилями cppcoreguidelines-*, modernize-*, performance-* ловит целую категорию багов и антипаттернов. Добавьте include-what-you-use, чтобы чистить заголовки и сокращать время сборки. Cppcheck и PVS-Studio (коммерческий) - хорошее дополнение, особенно для больших монореп.

Сборка и скорость. Используйте Ninja - быстрый планировщик задач. Кэшируйте компиляцию: ccache (Linux/macOS) или sccache (кросс-платформенно, умеет в удалённый кэш и S3). На линковке экономит mold (очень быстрый линкер для ELF) и lld от LLVM - обычно в 2-5 раз быстрее классических. Для больших проектов помогают precompiled headers и Unity-билды (в CMake: CMAKE_UNITY_BUILD=ON).

Зависимости. vcpkg хорош с манифестами (vcpkg.json) и кросс-платформенными triplet’ами; Conan 2 даёт профили и локфайлы, удобен для приватных артефактов. Советы: фиксируйте версии, храните локфайлы в репозитории, для критичных библиотек делайте vendoring (вендорный сабмодуль), чтобы не зависеть от сбоя зеркал.

CMake по-взрослому. Описывайте всё через цели: add_library(foo) + target_link_libraries(foo PRIVATE ...) + target_compile_features(foo PUBLIC cxx_std_20) + target_include_directories(foo PUBLIC ...). Не используйте глобальные include_directories() и add_definitions(). Для модулей C++20 в CMake базовая поддержка появилась в 3.28+, но экосистема ещё догоняет: начинайте с небольших целей, следите за кешированием BMI. Генератор - Ninja, пресеты - CMakePresets.json.

Профилировка и трейсинг. На Linux стартуйте с perf + flamegraph’ы (скрипты Brendan Gregg), для памяти - heaptrack или Valgrind Massif. Intel VTune помогает с векторизацией и узкими местами памяти; на AMD - uProf. На Windows используйте Visual Studio Profiler и Windows Performance Analyzer (ETW). Для событийной трассировки удобны LTTng/Perfetto; экспорт в Chrome Trace Viewer даёт наглядную картину задержек.

Бенчмаркинг. Google Benchmark - де-факто стандарт. Обязательно добавляйте benchmark::DoNotOptimize(x) и benchmark::ClobberMemory(), чтобы компилятор не выкинул работу. Гоняйте бенчи на «тёплом» CPU, фиксируйте частоты (performance governor на Linux), отключайте турбо, если ищете стабильность. Снимайте не только среднее, но и p95/p99 - хвосты важнее для продакшена.

Тесты и фуззинг. Юнит-тесты - GoogleTest или Catch2, быстрый старт - doctest (быстрый, без лишних зависимостей). Покрытие: llvm-cov + gcovr/lcov. Фуззинг: libFuzzer (LLVM), AFL++ и Honggfuzz. Лучший эффект - в связке с санитайзерами; падает - значит нашли ошибку. Для API с бинарными форматами добавьте корпус реальных образцов и проверяйте, что парсер не падает на мусоре.

Логи и метрики. Быстрый лог - spdlog, форматирование - fmt. Для структурированных логов добавляйте поля (ключ-значение) и таймстемпы в один ряд, чтобы не мучить парсеры. Метрики: prometheus-cpp, экспонируйте /metrics и следите за p99, аллокациями и количеством активных потоков. Дистрибьютед-трейсинг: opentelemetry-cpp, экспортер в Jaeger/OTLP.

Производительность сборок и бинарей. Включайте LTO (-flto) и PGO: -fprofile-generate - собрали, прогрели на реальных сценариях, затем -fprofile-use. Практический выигрыш 5-20% - реальность, если код CPU-bound. Для ELF-бинарей после линковки попробуйте BOLT (post-link оптимизатор от Meta) - иногда ещё несколько процентов.

Безопасность и харднинг. На Linux: -fstack-protector-strong, -D_FORTIFY_SOURCE=3 (с новыми glibc), PIE: -fPIE -pie, линковка: -Wl,-z,relro,-z,now. В libstdc++ включайте ассерты: -D_GLIBCXX_ASSERTIONS в Debug/Asan. На Windows: /guard:cf, /Qspectre, включите Control Flow Guard и ASLR. Проверьте зависимости на известные уязвимости (OSV, GitHub Dependabot).

ABI и плагины. Если делаете публичную библиотеку, спрячьте символы по умолчанию: -fvisibility=hidden и экспортируйте только API через макросы. Это ускоряет линковку и уменьшает риск конфликтов. Семантическое версионирование + чёткая политика ABI (отдельные сборки для Debug/Release) сэкономят кучу нервов.

Кроссплатформенность. С самого начала держите CI-матрицу: Ubuntu LTS, Windows Server, macOS. Избегайте неявных допущений об эндianness и выравнивании, не разыменовывайте неполные типы, не храните «сырые» указатели дольше владельцев. Пользуйтесь std::filesystem вместо самописных путей, std::span/std::string_view вместо сырых пар ptr+len.

Краш-репорты. На десктопах отлично работает Crashpad (форк Breakpad) - собирает minidump’ы на Windows/macOS/Linux. Символизируйте стеки на сервере, привязывайте к commit SHA. Это лучше, чем «не воспроизводится на моей машине».

Минимальные правила для PR, чтобы код держался в форме:

  • Пробег по clang-format и clang-tidy.
  • Сборка Debug+ASan/UBSan, прогон юнит-тестов.
  • Быстрый фуззинг час-два на изменённых парсерах.
  • Один профилировочный прогон «горячих» путей перед мёрджем.

И последнее: меряйте. Не верьте ощущениями, смотрите профили, графики и p99. Это самый короткий путь к надёжному и быстрому коду.

Написать комментарий