SlideShare a Scribd company logo
1 of 45
Оптимизация сборки С++ проектов
Способы, поддержка и
последствия
1
План доклада 2
• Стартовые условия.
• Ускорение компиляции.
• Ускорение линковки.
• В каждом способе ускорения отдельно рассмотрим влияние на кодобазу и затраты на
поддержку.
Стартовые условия
3
Состояние кодобазы 4
• 10+ лет постоянного развития и добавления нового.
• Взрывной рост количества инженеров на проекте.
• Распределённая команда.
• Гайдлайны не успевают за фичами => разношёрстный код.
Основные кейсы для оптимизации 5
• Понять, в каком состоянии время сборки.
• Ускорение девелоперских итераций. Получение бинарника после правки одного .cpp.
• Full rebuild или крупные пересборки.
Как ускоряем?
• Ускоряем методиками, применимыми ко всему коду, без знания контекста.
• Проекты под Windows. Ориентация на них в первую очередь.
• Стремимся вырабатывать автоматические или полуавтоматические решения.
Зачем ускоряем?
Ускорение компиляции
6
Источник постоянных проблем 7
Способ достижения «модульности» не менялся много лет
Заголовочный файл
каждый раз
обрабатывается с нуля
// a.cpp
#include "vector3.hpp" // slow processing
// b.cpp
#include "vector3.hpp" // and again
// c.cpp
#include "vector3.hpp" // ...and again
// z10000.cpp
#include "vector3.hpp" // >_______<
8
Все не любят инклуды
Уменьшим затраты на обработку #include 9
• IWYU. Include-What-You-Use.
• PCH. Precompiled header.
• Unity Builds.
10
IWYU
IWYU 11
Include What You Use
// matrix.hpp
class Matrix{};
// matrix_to_ogg_converter.hpp
#include "matrix.hpp"
class YouDontNeedIt
{
Matrix m;
};
// your_header.hpp
#include "matrix_to_ogg_converter.hpp" // WHAT? FOR Matrix?!
#include "matrix.hpp"
class Some
{
Matrix m;
};
Как применить IWYU на существующем коде? 12
• Вручную конвертировать большую кодобазу почти невозможно.
• Давайте автоматизировать?
• Есть open-source решение – IWYU.
• Open-source требует доработки.
Эффект применения IWYU 13
• В ряде cpp выкинуло ряд не нужных для компиляции инклудов.
• Часть инклудов заменили на forward declaration.
• Время сборки некоторых крупных cpp, собиравшихся более 10 секунд, сократилось на 40%.
• В ходе работы инструмента можно собрать ряд полезной информации о зависимостях в
проекте.
Из хорошего
Эффект применения IWYU 14
• Внезапно, IWYU требует clang-компилируемую кодобазу.
• Результат ускорения пересборки всего клиента не сильно заметен, по сравнению с
компиляцией отдельных файлов. Основное подозрение – изначальное отсутствие
монолитных хедеров.
• Особенности некоторых third-party не позволяют полностью автоматически применять IWYU:
• Бывают «внутренние» заголовочные файлы.
• Иногда сам #include приводит к выполнению кода.
Из интересного
Так нужен ли IWYU? 15
• Да, т.к. отдельные файлы получают ускорение.
• Да, т.к. по отзывам обладателей монолитных хедеров (wot blitz, unreal) ускорение было 10+
процентов.
• Да, т.к. убираются откровенно ненужные связи между библиотеками.
• Visual Assist/Resharper упрощают вставку хедеров. Но их нужно перепроверять.
Практика и инструмент
IWYU - Затраты на поддержку 16
• Требуется постоянное ревью кода.
• Автоматизированного универсального способа валидации пока (?) нет.
• Сделать полностью автономный инструмент своими силами не самая простая задача.
• Существующий IWYU инструмент требует компилируемый clang код.
17
PCH
PCH 18
Precompiled Headers
Заголовочный файл
каждый раз
обрабатывается с нуля
// a.cpp
#include "vector3.hpp" // slow processing
// b.cpp
#include "vector3.hpp" // and again
// c.cpp
#include "vector3.hpp" // ...and again
// z10000.cpp
#include "vector3.hpp" // >_______<
PCH 19
Precompiled Headers
// pch.hpp
#include “vector3.hpp"
Тяжеловесная обработка
vector3.hpp только в
pch.hpp
// a.cpp
#include “pch.hpp"
#include "vector3.hpp"
// b.cpp
#include “pch.hpp"
#include "vector3.hpp“
// c.cpp
#include “pch.hpp"
#include "vector3.hpp"
// z10000.cpp
#include “pch.hpp"
#include "vector3.hpp"
Напишем PCH 20
• Понять, а какие third-party headers нужны для либы.
• Понять, какие наши headers использует либа.
• Скомпоновать из них такой PCH, который компилируется.
• Обработать сотню уже существующих либ. В нашем случае выкинуть ещё и старые pch.
• Периодически обновлять PCH
Что нужно для написания PCH?
Решение - Автоматика 21
• Cotire
• Требует Single Compilation Unit.
• Придётся допиливать под наши проекты.
• Собственный PCH-генератор
• Пишем для наших проектов, зная внутреннюю специфику
• Анализируем include graph
Оскал суровой реальности 22
• В инклуд графе есть .inl, .ipp и прочий кошмар.
• Некоторые заголовочные файлы нельзя включать вручную.
• Некоторые заголовочные файлы работают только в определённом порядке.
• Все собственные заголовочные файлы вставлять тоже не стоит.
Решение
• White list хедеров (“мега-pch”), являющийся фильтром include graph.
Headers так просто в PCH не лезут.
Негативные последствия 23
• Очевидное: слишком связные PCH приводят к более частой рекомпиляции.
• Менее очевидное, но болезненное: с течением времени кодобаза становится более
хрупкой.
• Устанавливаются дополнительные связи в коде. Рассмотрим примеры.
Типовые дефекты в инклудах
24
1. Cpp забыл часть заголовочных файлов 25
Ряд зависимостей вставляется только через pch.hpp
// a.cpp
#include "pch.hpp"
#include <string>
#include <vector>
std::string coolFunc(std::vector<int> a)
{
return "";
}
2. Header содержит неполный набор зависимостей 26
Как добавить веселья коллеге
// a.hpp
#pragma once
#include <string>
class B;
B* coolFactory(std::string name);
// a.cpp
#include "pch.hpp"
#include "a.hpp"
#include “b.hpp”
B* coolFactory(std::string name)
{
return new B();
}
3. ifdef в header без дефайна 27
«Я случайно флаг»
// a.hpp
#pragma once
#include "debug_flag.hpp"
#ifdef SOME_DEBUG_FLAG
#include "debug_flag.hpp" // WHY?!
int myCoolDebugFunc();
#endif
// any other user cpp
#include "pch.hpp"
#include "a.hpp"
#include "debug_flag.hpp"
// debug_flag.hpp
#pragma once
#define SOME_DEBUG_FLAG 1
Есть ли выход из этой ситуации? 28
Почему всё так? 29
• Environment позволяет сделать «случайно» компилирующиеся .cpp.
• Не обращали внимания, пока проблема не стала слишком большой.
• Ни компилятор, ни инструменты типа VAssist/Resharper не показывают ошибки при инклудах
через pch.
• На старте работ по автоматизации PCH пришлось руками разгребать накопившиеся
проблемы. IWYU помог в улучшении ситуации.
Self-contained headers! 30
Заголовочные файлы, компилирующиеся без посторонней помощи в .cpp
// self_contained.hpp
#pragma once
#include <debug_flag.hpp>
#include <vector>
class B;
#if SOME_DEBUG_FLAG
std::vector<int> createSequence(const B& b);
#endif
// ANY .cpp
#include "self_contained.hpp“ // The First
Эффект от применения 31
• 15% ускорения full rebuild в сравнении с написанными вручную.
• Более чем двукратное (x2) ускорение в сравнении с отсутствием PCH.
• Наличие генератора с заранее описанным алгоритмом снимает головную боль при
написании новых pch для новых либ.
Затраты на поддержку 32
• Дополнительная nightly проверка.
• Проверка пытается собрать клиент с отключёнными PCH. Ошибки компиляции/линковки –
валидация не пройдена.
• Периодически нужно актуализировать pch.
Требуется дополнительный контроль за pch-зависимостями
Unity Builds 33
• Ещё более ярко выражены плюсы и минусы в сравнении с PCH.
• Требуют модификации кода, специфичного только для Unity Builds:
• Убрать одинаковые static символы и символы в анонимных неймспейсах.
• #undef макросов.
• Убрать using на весь .cpp.
• Порядок следования .cpp также имеет значение.
• Потенциальное замедление мелких итераций (сборка нескольких .cpp вместо одного).
• Следствие: в нашем проекте (пока?) не используем, т.к. требует дополнительных затрат на
внедрение и поддержку с неясными перспективами.
Ускорение линковки
34
Почему важно ускорить? 35
• При мелких итерациях может быть в несколько раз дольше компиляции.
• Практически константна по времени независимо от .cpp.
• Даже мельчайшая итерация занимала больше минуты, а то и полутора. Из них более минуты
– линковка.
Инкрементальная линковка 36
• Отключить любые оптимизации линковки.
• Отключить /GL опцию компилятора. Опция вирусная, любое появление ломает
инкрементальную линковку.
• Отключить mt.exe.
Как сделать (MSVC)
Инкрементальная линковка 37
• Ускорение малых итераций в несколько раз при срабатывании.
• Не всегда срабатывает. (Новый .obj – full relink, например).
• Увеличение размера бинарников (у нас – двукратно).
• Падение производительности (у нас -10% FPS).
• Как следствие, непригодна для QA и для хранения.
• Но вполне ОК для локальной работы.
Эффект
Инкрементальная линковка 38
• Нужно иметь два варианта сборки бинарников: локальная сборка и обычная, для билд-
машин.
• Помнить про /GL опцию и не допускать её наличия в варианте «локальной сборки».
• /VERBOSE:INCR
Затраты на поддержку
FastLink 39
• Доехала в VS2017.
• Экономит за счёт убирания переноса данных в pdb.
• Меньше требований к опциям компилятора.
MSVC-specific
FastLink 40
• Работает устойчиво.
• Ухудшения производительности не обнаружено.
• Можно и нужно комбинировать с инкрементальной линковкой.
• Иногда в дебаге наблюдаются задержки в получении информации о символах.
Эффект
FastLink 41
• Две сборки (локальная и для билдмашин).
• Помнить, что pdb, собранный при FastLink, не подходит для хранения в сервере символов.
Затраты на поддержку
Что осталось за скобками 42
• Распутывание зависимостей. Творческий и нудный процесс одновременно.
• Extern template? – В теории должен помогать, но непонятно, к чему подступиться.
• Распределённая сборка – IncrediBuild (~6:30 vs ~5 минут).
Выводы
43
Выводы 44
• Практика IWYU полезна как для скорости сборки, так и для контроля зависимостей.
• Нужно следовать практике self-contained headers.
• PCH очень полезны для ускорения сборки, но нужно оберегать кодобазу от паразитных
связей из-за них.
• Unity Builds – up to you. Как PCH, но с ещё более ярко выраженными плюсами и минусами.
• Линковку можно радикально ускорить для локальных сборок.
• Без внутренних гайдлайнов по этим вопросам поддержка ухудшается.
• Без автоматизированных проверок эти процедуры тем более постепенно протухают.
• Ручная обработка крупной кодобазы почти нереальна.
45
Вопросы?
Александр Жоров, Senior Engine Developer, Wargaming.net
Email: a_jorov@wargaming.net
Telegram: @SlideGauge

More Related Content

What's hot

"Девопс - это не только для программистов. Практические примеры из жизни одно...
"Девопс - это не только для программистов. Практические примеры из жизни одно..."Девопс - это не только для программистов. Практические примеры из жизни одно...
"Девопс - это не только для программистов. Практические примеры из жизни одно...
it-people
 
Мастер класс- Maven + Jenkins
Мастер класс- Maven + JenkinsМастер класс- Maven + Jenkins
Мастер класс- Maven + Jenkins
Valentin Fedoskin
 
Иван Крутов - Автоматизация сборки Java-проекта
Иван Крутов - Автоматизация сборки Java-проектаИван Крутов - Автоматизация сборки Java-проекта
Иван Крутов - Автоматизация сборки Java-проекта
Yandex
 
SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...
SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...
SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...
SECON
 
Клиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на JavaКлиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на Java
Nikita Lipsky
 
Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)
Ontico
 
Big web project @happydev Omsk
Big web project @happydev OmskBig web project @happydev Omsk
Big web project @happydev Omsk
Alex Chistyakov
 
Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...
Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...
Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...
HappyDev
 
Scripting languages
Scripting languagesScripting languages
Scripting languages
Lev Panov
 

What's hot (20)

"Девопс - это не только для программистов. Практические примеры из жизни одно...
"Девопс - это не только для программистов. Практические примеры из жизни одно..."Девопс - это не только для программистов. Практические примеры из жизни одно...
"Девопс - это не только для программистов. Практические примеры из жизни одно...
 
Григорий Петров "WebRTC в мобильных приложениях при помощи React Native"
Григорий Петров "WebRTC в мобильных приложениях при помощи React Native"Григорий Петров "WebRTC в мобильных приложениях при помощи React Native"
Григорий Петров "WebRTC в мобильных приложениях при помощи React Native"
 
Performance engineering stories from #fdminicon Saransk
Performance engineering stories from #fdminicon SaranskPerformance engineering stories from #fdminicon Saransk
Performance engineering stories from #fdminicon Saransk
 
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на LinuxПавел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
Павел Беликов, Опыт мигрирования крупного проекта с Windows-only на Linux
 
Введение в maven
Введение в mavenВведение в maven
Введение в maven
 
Мастер класс- Maven + Jenkins
Мастер класс- Maven + JenkinsМастер класс- Maven + Jenkins
Мастер класс- Maven + Jenkins
 
"Prom.ua shopping cart workflow as a microfrontend", Danylo Kazymyrov
"Prom.ua shopping cart workflow as a microfrontend", Danylo Kazymyrov"Prom.ua shopping cart workflow as a microfrontend", Danylo Kazymyrov
"Prom.ua shopping cart workflow as a microfrontend", Danylo Kazymyrov
 
Иван Крутов - Автоматизация сборки Java-проекта
Иван Крутов - Автоматизация сборки Java-проектаИван Крутов - Автоматизация сборки Java-проекта
Иван Крутов - Автоматизация сборки Java-проекта
 
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемыMoscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
 
Эксплуатация container-based-инфраструктур / Николай Сивко (okmeter.io)
Эксплуатация container-based-инфраструктур / Николай Сивко (okmeter.io)Эксплуатация container-based-инфраструктур / Николай Сивко (okmeter.io)
Эксплуатация container-based-инфраструктур / Николай Сивко (okmeter.io)
 
SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...
SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...
SECON'2017, Кулагин Егор, Непрерывное развертывание. Конвейер здорового челов...
 
Клиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на JavaКлиентская Java вне браузера. Делаем нативные клиенты на Java
Клиентская Java вне браузера. Делаем нативные клиенты на Java
 
My talk on Docker from Moscow Django Meetup #25
My talk on Docker from Moscow Django Meetup #25My talk on Docker from Moscow Django Meetup #25
My talk on Docker from Moscow Django Meetup #25
 
Кирилл Комлев. О реализации continuous integration для web проектов
Кирилл Комлев. О реализации continuous integration для web проектовКирилл Комлев. О реализации continuous integration для web проектов
Кирилл Комлев. О реализации continuous integration для web проектов
 
Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)Конструктор / Денис Паясь (Яндекс)
Конструктор / Денис Паясь (Яндекс)
 
Big web project @happydev Omsk
Big web project @happydev OmskBig web project @happydev Omsk
Big web project @happydev Omsk
 
Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...
Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...
Александр Чистяков - Большой веб-проект: развитие, рост, проблемы, решения с ...
 
Кэширование в веб-приложениях: что? где? когда?
Кэширование в веб-приложениях: что? где? когда?Кэширование в веб-приложениях: что? где? когда?
Кэширование в веб-приложениях: что? где? когда?
 
Страх и ненависть в мире релиз-инжиниринга
Страх и ненависть в мире релиз-инжинирингаСтрах и ненависть в мире релиз-инжиниринга
Страх и ненависть в мире релиз-инжиниринга
 
Scripting languages
Scripting languagesScripting languages
Scripting languages
 

Similar to C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последствия - Александр Жоров

Анти шаблоны непрерывной интеграции
Анти шаблоны непрерывной интеграцииАнти шаблоны непрерывной интеграции
Анти шаблоны непрерывной интеграции
SQALab
 
13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...
13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...
13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...
IT-Portfolio
 
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
HappyDev
 
Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)
Ontico
 
Javascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только одинJavascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только один
Sergey Xek
 
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Ontico
 

Similar to C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последствия - Александр Жоров (20)

"How to build powerful CI / CD based on GitLab and Docker", Aleksandr Matkovs...
"How to build powerful CI / CD based on GitLab and Docker", Aleksandr Matkovs..."How to build powerful CI / CD based on GitLab and Docker", Aleksandr Matkovs...
"How to build powerful CI / CD based on GitLab and Docker", Aleksandr Matkovs...
 
Анти шаблоны непрерывной интеграции
Анти шаблоны непрерывной интеграцииАнти шаблоны непрерывной интеграции
Анти шаблоны непрерывной интеграции
 
Непрерывная интеграция при разработке баз данных. (Show version)
Непрерывная интеграция при разработке баз данных. (Show version)Непрерывная интеграция при разработке баз данных. (Show version)
Непрерывная интеграция при разработке баз данных. (Show version)
 
Ansible in the enterprise
Ansible in the enterpriseAnsible in the enterprise
Ansible in the enterprise
 
Как мы собираем проекты в выделенном окружении в Windows Docker
Как мы собираем проекты в выделенном окружении в Windows DockerКак мы собираем проекты в выделенном окружении в Windows Docker
Как мы собираем проекты в выделенном окружении в Windows Docker
 
Юрий Василевский "Автоматизация в XCode"
Юрий Василевский "Автоматизация в XCode"Юрий Василевский "Автоматизация в XCode"
Юрий Василевский "Автоматизация в XCode"
 
Юрий Василевский «Автоматизация в XCode»
Юрий Василевский «Автоматизация в XCode»Юрий Василевский «Автоматизация в XCode»
Юрий Василевский «Автоматизация в XCode»
 
13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...
13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...
13 октября, DEV {web} - конференция о Highload веб-разработке. "Управление ок...
 
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
2015-12-05 Сергей Аверин - Javascript-фреймворки: должен остаться только один
 
Как hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качествеКак hh.ru дошли до 500 релизов в квартал без потери в качестве
Как hh.ru дошли до 500 релизов в квартал без потери в качестве
 
Типовая сборка и деплой продуктов в Positive Technologies
Типовая сборка и деплой продуктов в Positive TechnologiesТиповая сборка и деплой продуктов в Positive Technologies
Типовая сборка и деплой продуктов в Positive Technologies
 
Chef @DevWeb
Chef @DevWebChef @DevWeb
Chef @DevWeb
 
Pconnect: граната в руках обезьяны
Pconnect: граната в руках обезьяныPconnect: граната в руках обезьяны
Pconnect: граната в руках обезьяны
 
Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)Pconnect: граната в руках обезьяны (Сергей Аверин)
Pconnect: граната в руках обезьяны (Сергей Аверин)
 
Unity: WebGL и IL2CPP — будущее скриптинга в Unity»
Unity: WebGL и IL2CPP — будущее скриптинга в Unity»Unity: WebGL и IL2CPP — будущее скриптинга в Unity»
Unity: WebGL и IL2CPP — будущее скриптинга в Unity»
 
Javascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только одинJavascript-фреймворки:
 должен остаться только один
Javascript-фреймворки:
 должен остаться только один
 
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
Javascript-фреймворки: должен остаться только один / Аверин Сергей (Acronis)
 
Sivko
SivkoSivko
Sivko
 
Breaking logs
Breaking logsBreaking logs
Breaking logs
 
AgileCamp’11 Новосибирск - Continuous Integration (CI)
AgileCamp’11 Новосибирск - Continuous Integration (CI)AgileCamp’11 Новосибирск - Continuous Integration (CI)
AgileCamp’11 Новосибирск - Continuous Integration (CI)
 

More from corehard_by

C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
corehard_by
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
corehard_by
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
corehard_by
 

More from corehard_by (20)

C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
C++ CoreHard Autumn 2018. Создание пакетов для открытых библиотек через conan...
 
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
C++ CoreHard Autumn 2018. Что должен знать каждый C++ программист или Как про...
 
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений ОхотниковC++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
C++ CoreHard Autumn 2018. Actors vs CSP vs Tasks vs ... - Евгений Охотников
 
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр ТитовC++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
C++ CoreHard Autumn 2018. Знай свое "железо": иерархия памяти - Александр Титов
 
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
C++ CoreHard Autumn 2018. Информационная безопасность и разработка ПО - Евген...
 
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья ШишковC++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
C++ CoreHard Autumn 2018. Заглядываем под капот «Поясов по C++» - Илья Шишков
 
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
C++ CoreHard Autumn 2018. Метаклассы: воплощаем мечты в реальность - Сергей С...
 
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
C++ CoreHard Autumn 2018. Что не умеет оптимизировать компилятор - Александр ...
 
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
C++ CoreHard Autumn 2018. Кодогенерация C++ кроссплатформенно. Продолжение - ...
 
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
C++ CoreHard Autumn 2018. Concurrency and Parallelism in C++17 and C++20/23 -...
 
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
C++ CoreHard Autumn 2018. Обработка списков на C++ в функциональном стиле - В...
 
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел ФилоновC++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
C++ Corehard Autumn 2018. Обучаем на Python, применяем на C++ - Павел Филонов
 
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan ČukićC++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
C++ CoreHard Autumn 2018. Asynchronous programming with ranges - Ivan Čukić
 
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia KazakovaC++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
C++ CoreHard Autumn 2018. Debug C++ Without Running - Anastasia Kazakova
 
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон ПолухинC++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
C++ CoreHard Autumn 2018. Полезный constexpr - Антон Полухин
 
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
C++ CoreHard Autumn 2018. Text Formatting For a Future Range-Based Standard L...
 
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
Исключительная модель памяти. Алексей Ткаченко ➠ CoreHard Autumn 2019
 
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019Как помочь и как помешать компилятору. Андрей Олейников ➠  CoreHard Autumn 2019
Как помочь и как помешать компилятору. Андрей Олейников ➠ CoreHard Autumn 2019
 
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019Автоматизируй это. Кирилл Тихонов ➠  CoreHard Autumn 2019
Автоматизируй это. Кирилл Тихонов ➠ CoreHard Autumn 2019
 
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019Статичный SQL в С++14. Евгений Захаров ➠  CoreHard Autumn 2019
Статичный SQL в С++14. Евгений Захаров ➠ CoreHard Autumn 2019
 

C++ CoreHard Autumn 2018. Ускорение сборки C++ проектов, способы и последствия - Александр Жоров

  • 1. Оптимизация сборки С++ проектов Способы, поддержка и последствия 1
  • 2. План доклада 2 • Стартовые условия. • Ускорение компиляции. • Ускорение линковки. • В каждом способе ускорения отдельно рассмотрим влияние на кодобазу и затраты на поддержку.
  • 4. Состояние кодобазы 4 • 10+ лет постоянного развития и добавления нового. • Взрывной рост количества инженеров на проекте. • Распределённая команда. • Гайдлайны не успевают за фичами => разношёрстный код.
  • 5. Основные кейсы для оптимизации 5 • Понять, в каком состоянии время сборки. • Ускорение девелоперских итераций. Получение бинарника после правки одного .cpp. • Full rebuild или крупные пересборки. Как ускоряем? • Ускоряем методиками, применимыми ко всему коду, без знания контекста. • Проекты под Windows. Ориентация на них в первую очередь. • Стремимся вырабатывать автоматические или полуавтоматические решения. Зачем ускоряем?
  • 7. Источник постоянных проблем 7 Способ достижения «модульности» не менялся много лет Заголовочный файл каждый раз обрабатывается с нуля // a.cpp #include "vector3.hpp" // slow processing // b.cpp #include "vector3.hpp" // and again // c.cpp #include "vector3.hpp" // ...and again // z10000.cpp #include "vector3.hpp" // >_______<
  • 8. 8 Все не любят инклуды
  • 9. Уменьшим затраты на обработку #include 9 • IWYU. Include-What-You-Use. • PCH. Precompiled header. • Unity Builds.
  • 11. IWYU 11 Include What You Use // matrix.hpp class Matrix{}; // matrix_to_ogg_converter.hpp #include "matrix.hpp" class YouDontNeedIt { Matrix m; }; // your_header.hpp #include "matrix_to_ogg_converter.hpp" // WHAT? FOR Matrix?! #include "matrix.hpp" class Some { Matrix m; };
  • 12. Как применить IWYU на существующем коде? 12 • Вручную конвертировать большую кодобазу почти невозможно. • Давайте автоматизировать? • Есть open-source решение – IWYU. • Open-source требует доработки.
  • 13. Эффект применения IWYU 13 • В ряде cpp выкинуло ряд не нужных для компиляции инклудов. • Часть инклудов заменили на forward declaration. • Время сборки некоторых крупных cpp, собиравшихся более 10 секунд, сократилось на 40%. • В ходе работы инструмента можно собрать ряд полезной информации о зависимостях в проекте. Из хорошего
  • 14. Эффект применения IWYU 14 • Внезапно, IWYU требует clang-компилируемую кодобазу. • Результат ускорения пересборки всего клиента не сильно заметен, по сравнению с компиляцией отдельных файлов. Основное подозрение – изначальное отсутствие монолитных хедеров. • Особенности некоторых third-party не позволяют полностью автоматически применять IWYU: • Бывают «внутренние» заголовочные файлы. • Иногда сам #include приводит к выполнению кода. Из интересного
  • 15. Так нужен ли IWYU? 15 • Да, т.к. отдельные файлы получают ускорение. • Да, т.к. по отзывам обладателей монолитных хедеров (wot blitz, unreal) ускорение было 10+ процентов. • Да, т.к. убираются откровенно ненужные связи между библиотеками. • Visual Assist/Resharper упрощают вставку хедеров. Но их нужно перепроверять. Практика и инструмент
  • 16. IWYU - Затраты на поддержку 16 • Требуется постоянное ревью кода. • Автоматизированного универсального способа валидации пока (?) нет. • Сделать полностью автономный инструмент своими силами не самая простая задача. • Существующий IWYU инструмент требует компилируемый clang код.
  • 18. PCH 18 Precompiled Headers Заголовочный файл каждый раз обрабатывается с нуля // a.cpp #include "vector3.hpp" // slow processing // b.cpp #include "vector3.hpp" // and again // c.cpp #include "vector3.hpp" // ...and again // z10000.cpp #include "vector3.hpp" // >_______<
  • 19. PCH 19 Precompiled Headers // pch.hpp #include “vector3.hpp" Тяжеловесная обработка vector3.hpp только в pch.hpp // a.cpp #include “pch.hpp" #include "vector3.hpp" // b.cpp #include “pch.hpp" #include "vector3.hpp“ // c.cpp #include “pch.hpp" #include "vector3.hpp" // z10000.cpp #include “pch.hpp" #include "vector3.hpp"
  • 20. Напишем PCH 20 • Понять, а какие third-party headers нужны для либы. • Понять, какие наши headers использует либа. • Скомпоновать из них такой PCH, который компилируется. • Обработать сотню уже существующих либ. В нашем случае выкинуть ещё и старые pch. • Периодически обновлять PCH Что нужно для написания PCH?
  • 21. Решение - Автоматика 21 • Cotire • Требует Single Compilation Unit. • Придётся допиливать под наши проекты. • Собственный PCH-генератор • Пишем для наших проектов, зная внутреннюю специфику • Анализируем include graph
  • 22. Оскал суровой реальности 22 • В инклуд графе есть .inl, .ipp и прочий кошмар. • Некоторые заголовочные файлы нельзя включать вручную. • Некоторые заголовочные файлы работают только в определённом порядке. • Все собственные заголовочные файлы вставлять тоже не стоит. Решение • White list хедеров (“мега-pch”), являющийся фильтром include graph. Headers так просто в PCH не лезут.
  • 23. Негативные последствия 23 • Очевидное: слишком связные PCH приводят к более частой рекомпиляции. • Менее очевидное, но болезненное: с течением времени кодобаза становится более хрупкой. • Устанавливаются дополнительные связи в коде. Рассмотрим примеры.
  • 24. Типовые дефекты в инклудах 24
  • 25. 1. Cpp забыл часть заголовочных файлов 25 Ряд зависимостей вставляется только через pch.hpp // a.cpp #include "pch.hpp" #include <string> #include <vector> std::string coolFunc(std::vector<int> a) { return ""; }
  • 26. 2. Header содержит неполный набор зависимостей 26 Как добавить веселья коллеге // a.hpp #pragma once #include <string> class B; B* coolFactory(std::string name); // a.cpp #include "pch.hpp" #include "a.hpp" #include “b.hpp” B* coolFactory(std::string name) { return new B(); }
  • 27. 3. ifdef в header без дефайна 27 «Я случайно флаг» // a.hpp #pragma once #include "debug_flag.hpp" #ifdef SOME_DEBUG_FLAG #include "debug_flag.hpp" // WHY?! int myCoolDebugFunc(); #endif // any other user cpp #include "pch.hpp" #include "a.hpp" #include "debug_flag.hpp" // debug_flag.hpp #pragma once #define SOME_DEBUG_FLAG 1
  • 28. Есть ли выход из этой ситуации? 28
  • 29. Почему всё так? 29 • Environment позволяет сделать «случайно» компилирующиеся .cpp. • Не обращали внимания, пока проблема не стала слишком большой. • Ни компилятор, ни инструменты типа VAssist/Resharper не показывают ошибки при инклудах через pch. • На старте работ по автоматизации PCH пришлось руками разгребать накопившиеся проблемы. IWYU помог в улучшении ситуации.
  • 30. Self-contained headers! 30 Заголовочные файлы, компилирующиеся без посторонней помощи в .cpp // self_contained.hpp #pragma once #include <debug_flag.hpp> #include <vector> class B; #if SOME_DEBUG_FLAG std::vector<int> createSequence(const B& b); #endif // ANY .cpp #include "self_contained.hpp“ // The First
  • 31. Эффект от применения 31 • 15% ускорения full rebuild в сравнении с написанными вручную. • Более чем двукратное (x2) ускорение в сравнении с отсутствием PCH. • Наличие генератора с заранее описанным алгоритмом снимает головную боль при написании новых pch для новых либ.
  • 32. Затраты на поддержку 32 • Дополнительная nightly проверка. • Проверка пытается собрать клиент с отключёнными PCH. Ошибки компиляции/линковки – валидация не пройдена. • Периодически нужно актуализировать pch. Требуется дополнительный контроль за pch-зависимостями
  • 33. Unity Builds 33 • Ещё более ярко выражены плюсы и минусы в сравнении с PCH. • Требуют модификации кода, специфичного только для Unity Builds: • Убрать одинаковые static символы и символы в анонимных неймспейсах. • #undef макросов. • Убрать using на весь .cpp. • Порядок следования .cpp также имеет значение. • Потенциальное замедление мелких итераций (сборка нескольких .cpp вместо одного). • Следствие: в нашем проекте (пока?) не используем, т.к. требует дополнительных затрат на внедрение и поддержку с неясными перспективами.
  • 35. Почему важно ускорить? 35 • При мелких итерациях может быть в несколько раз дольше компиляции. • Практически константна по времени независимо от .cpp. • Даже мельчайшая итерация занимала больше минуты, а то и полутора. Из них более минуты – линковка.
  • 36. Инкрементальная линковка 36 • Отключить любые оптимизации линковки. • Отключить /GL опцию компилятора. Опция вирусная, любое появление ломает инкрементальную линковку. • Отключить mt.exe. Как сделать (MSVC)
  • 37. Инкрементальная линковка 37 • Ускорение малых итераций в несколько раз при срабатывании. • Не всегда срабатывает. (Новый .obj – full relink, например). • Увеличение размера бинарников (у нас – двукратно). • Падение производительности (у нас -10% FPS). • Как следствие, непригодна для QA и для хранения. • Но вполне ОК для локальной работы. Эффект
  • 38. Инкрементальная линковка 38 • Нужно иметь два варианта сборки бинарников: локальная сборка и обычная, для билд- машин. • Помнить про /GL опцию и не допускать её наличия в варианте «локальной сборки». • /VERBOSE:INCR Затраты на поддержку
  • 39. FastLink 39 • Доехала в VS2017. • Экономит за счёт убирания переноса данных в pdb. • Меньше требований к опциям компилятора. MSVC-specific
  • 40. FastLink 40 • Работает устойчиво. • Ухудшения производительности не обнаружено. • Можно и нужно комбинировать с инкрементальной линковкой. • Иногда в дебаге наблюдаются задержки в получении информации о символах. Эффект
  • 41. FastLink 41 • Две сборки (локальная и для билдмашин). • Помнить, что pdb, собранный при FastLink, не подходит для хранения в сервере символов. Затраты на поддержку
  • 42. Что осталось за скобками 42 • Распутывание зависимостей. Творческий и нудный процесс одновременно. • Extern template? – В теории должен помогать, но непонятно, к чему подступиться. • Распределённая сборка – IncrediBuild (~6:30 vs ~5 минут).
  • 44. Выводы 44 • Практика IWYU полезна как для скорости сборки, так и для контроля зависимостей. • Нужно следовать практике self-contained headers. • PCH очень полезны для ускорения сборки, но нужно оберегать кодобазу от паразитных связей из-за них. • Unity Builds – up to you. Как PCH, но с ещё более ярко выраженными плюсами и минусами. • Линковку можно радикально ускорить для локальных сборок. • Без внутренних гайдлайнов по этим вопросам поддержка ухудшается. • Без автоматизированных проверок эти процедуры тем более постепенно протухают. • Ручная обработка крупной кодобазы почти нереальна.
  • 45. 45 Вопросы? Александр Жоров, Senior Engine Developer, Wargaming.net Email: a_jorov@wargaming.net Telegram: @SlideGauge