Короткий ответ: на 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++ незаменим
Если вам нужна минимальная задержка, прямой доступ к памяти и железу, предсказуемость под нагрузкой - берут 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 с) |
Медиа/RTC | WebRTC, 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/GPU | CUDA, SYCL/oneAPI, TBB, Eigen | Доступ к SIMD/GPU, нулевые абстракции | Макс. близко к пику FLOPS, высокое L1/L2 hit‑rate |
Встраиваемые/RT | ROS 2, FreeRTOS/Zephyr приложения | Малая память, жёсткий тайминг ISR | RAM 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 | Бюджет кадра (мс) | Где это важно |
---|---|---|
30 | 33.33 | Кинематографичность, слабое железо |
60 | 16.67 | База для ПК/консолей |
90 | 11.11 | VR (часто целятся в 90+) |
120 | 8.33 | Мониторы 120 Гц, next‑gen консоли |
144 | 6.94 | Соревновательные шутеры на ПК |
240 | 4.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.
Пять шагов, чтобы быстро собрать прототип рендера и не увязнуть:
- Соберите окружение: CMake + компилятор (Clang/GCC/MSVC), заведите vcpkg или Conan для зависимостей.
- Создайте окно и контекст: GLFW/SDL2 + backend (D3D12/Vulkan/Metal).
- Сделайте минимальный пайплайн: загрузите шейдеры, подготовьте вершинный буфер, отрендерьте треугольник. Сразу подключите RenderDoc.
- Добавьте систему ресурсов: ассет‑пак, отдельный поток ввода‑вывода, декодер текстур (stb_image) и фоновые загрузки (корутины).
- Поставьте метрики: средний и 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).
Проект | Год | Ядро/язык | Класс задачи | Подтверждённый факт |
---|---|---|---|---|
ClickHouse | 2016 | C++ | OLAP СУБД | Колонночная, SIMD-векторизация, ZSTD/LZ4; собственный ClickHouse Keeper на Raft |
RocksDB | 2013 | C++ | KV (LSM) | Используется в Kafka Streams, TiKV, Flink как state backend |
MongoDB (Core) | 2009 | C++ | Документная СУБД | Движок хранения WiredTiger интегрирован; серверная часть написана на C++ |
ScyllaDB | 2015 | C++/Seastar | Wide-column | Thread-per-core, shared-nothing; миллионы ops/sec на узел |
Envoy | 2016 | C++ | L7-прокси | Широко используется в Istio как data plane |
Redpanda | 2020 | C++/Seastar | Брокер событий | Совместим с Kafka API, без JVM, ориентирован на низкую задержку |
gRPC C++ | 2015 | C/C++ | RPC | C++-клиент и сервер поверх C-core, поддержка HTTP/2 |
QuickFIX | 2001 | C++ | 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 в проде:
- Зафиксируйте частоту CPU и энергосхему (performance), привяжите потоки к ядрам и учтите NUMA.
- Сначала профилируйте (perf + FlameGraph), потом оптимизируйте «верхние» 20% горячих мест.
- Соберите с sanitizers и включите clang-tidy в CI - ловите undefined behavior до релиза.
- Измеряйте на боеподобной нагрузке: реальный размер сообщений, реальные шаблоны запросов.
- Следите за 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: держите обработчик коротким и без блокировок - делегируйте «тяжёлую» работу задаче.
- В ISR: читаем/записываем регистры, кладём событие в кольцевой буфер или очередь, выходим.
- В задаче: обрабатываем пакеты, считаем контрольные суммы, шлём дальше.
- Для приоритетной обработки используйте уведомления задач (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. Это самый короткий путь к надёжному и быстрому коду.
Написать комментарий