Профілювання процесу компіляції на C ++


79

Я схильний писати досить великі шаблонні бібліотеки C ++ лише для заголовків, і мої користувачі зазвичай скаржаться на час компіляції. Подумавши над цим, мені спало на думку, що я не уявляю, куди йде час . Чи існує якийсь простий спосіб профілювати процес компіляції C ++ за допомогою загальних компіляторів, таких як g ++, icc та xlC? Наприклад, чи можна скласти уявлення про те, скільки часу витрачається на кожній з фаз компіляції C ++ ?


2
stackoverflow.com/questions/82128/… для візуальної студії
Karthik T

2
@KarthikT Я ціную пропозицію, але мене цікавить набагато детальніша інформація, ніж ця (і для більш широкого кола компіляторів). Наприклад, якщо я буду будувати один об’єктний файл із бібліотеки, що містить лише заголовки, як я можу побачити, куди пішов час?
Джек Поулсон,

Я бачу, я не можу знайти нічого більш тонкого, ніж це, вибачте.
Karthik T

Відповіді:


66

Для GCC є варіанти налагодження для пошукуhow much time is spent within each of the phases of C++ compilation?

-Q Змушує компілятор роздруковувати кожну назву функції у міру її компіляції та друкувати деякі статистичні дані про кожен прохід, коли він закінчується.

-ftime-report Змушує компілятор надрукувати деякі статистичні дані про час, витрачений кожним проходом, коли він закінчується.

Пропуски описані в GCCINT 9: Пропуски та файли компілятора .

Ви можете опублікувати висновок компіляції g ++ з одного вихідного файлу -v -ftime-reportтут, щоб обговорити це . У списку розсилки GCC може бути якась допомога .


Для компіляторів , відмінних від GCC (або GCC більш давнього , ніж 3.3.6 ) подивитися інші варіанти в цій темі.


2
PS: -Qвихід можна захопити, проаналізувати та проаналізувати за допомогою якогось сценарію awk або perl; або ви можете просто спостерігати за друком імен функцій на консолі, будь-яку, яка була надрукована після тривалої паузи, було складно скласти.
osgx 03.03.15

Будь-яка ідея, як приєднати синхронізацію до назв функцій (за винятком злому g ++)? У мене є файл розміром 200 Мб із безладдям спагетті функцій, і я не знаю, яку функцію потрібно було скомпілювати. Вони в основному швидко компілюються, їх просто багато (це також важкий код шаблону). Я думав про конвеєр та сценарій, але конвеєри мають певний буфер, і функції з короткими іменами можуть не потрапити туди, поки не буде надруковано більше.
свині

1
свині, спробуйте зігріти 'quiet_flag' у gcc / cgraphunit.c та gcc/toplev.c( announce_function - "коли аналізується початок визначення функції, ця функція друкує на stderr ім'я функції"). Це announce_functionможе мати сенс додати друк позначки часу (gettimeofday) або переписати вихідні дані яким-небудь небуферним способом. Або іншим можливим способом є увімкнення дампів налагодження ( -fdump-rtl-all-all -fdump-tree-all-all -fdump-ipa-all-all), але вони видаватимуть 1 файл за прохід; вам потрібно перетворити їх для виведення 1 файлу на прохід і на функцію (отримати багато файлів із часом створення).
osgx

14

Існує інструмент проекту Boost, який може бути корисним практично для будь-якого компілятора та системи збірки.

Інструмент вимагає вихідного коду приладів з TEMPLATE_PROFILE_ENTER()і TEMPLATE_PROFILE_EXIT()макро - викликів. Потім ці макроси генерують специфічну діагностику (попередження) під час компіляції, яка синхронізується та збирається разом із екземплярами викликів (які, отже, дозволяють створювати та візуалізувати графіки викликів) за допомогою сценарію. Непогано, ІМО.

Хоча я його ще не використовував.


На його сторінці документації я не бачу необхідності в інструментарії вихідного коду. Де ви це читали?
lrineau

@Irineau, у джерелі. Інструмент також надає деякі сценарії, які, здається, автоматично виконують інструментарій на ходу (хоча з невідомим ступенем деталізації).
ulidtko

1
Посилання мертве.
rustyx

Ну @rustyx це не дивно, бачачи svn .boost.org в URL і 21 століття на годиннику ... Хтось завантажив виделку / дзеркало / перезапис? цього, хоча, можливо, це допомагає.
ulidtko

9

Clang 9 (і новіший) має -ftime-traceпрапор, що змушує його виводити звіт про профілювання як JSON (на додаток до файлу об'єкта).

Ви можете імпортувати цей файл у профайлер, який постачається з Chrome ( chrome://tracing), щоб отримати гарну візуалізацію:

рис

Стовпчики відповідають заголовкам, які потрібно було проаналізувати, а для кожного заголовка - певні класи (і, можливо, інші конструкції), які потрібно було проаналізувати. Він також повідомляє про час, витрачений на створення конкретних шаблонів.


7

Я ще не пробував, але templight виглядає ДУЖЕ багатообіцяючим: https://github.com/mikael-s-persson/templight


1
на жаль, це вимагає виправлення та нарощування дзвінків з джерела. не кінець світу, а чесне зобов’язання (припускаючи, що патч навіть застосовується)
xaxxon

5

Ви можете їх певною мірою відокремити (я припускаю make)

  • додати правило збірки, яке попередньо обробляє файли (за допомогою -Eкомутатора), і .PHONYціль, яка залежить від вихідних файлів препроцесора, як і звичайна двійкова мета.o файлів. Виміряйте, скільки часу потрібно для побудови цієї цілі
  • додати 'PHONYціль, яка залежить від усіх.o файлів, але не пов’язує їх. Виміряйте, скільки часу потрібно для побудови цієї цілі (з чистого)
  • Виміряйте, скільки часу потрібно для чистого складання звичайного двійкового файлу

Тепер ви трохи уявляєте, скільки часу потрібно для попередньої обробки, компіляції та зв’язування. Ви також можете порівняти оптимізовану та неоптимізовану ( -O0) версії другої та третьої цілей, щоб побачити, скільки часу витрачається в оптимізаторі.


Дякую за відповідь. Я думаю, що це було б більш ніж достатнім для програм на С, але для заголовка лише на C ++, який не створює більше одного .o-файлу, майже весь час буде витрачено на створення єдиного .o. Я голосую за, але схрещу пальці, що хтось запропонує більш дрібний підхід.
Джек Поулсон,

А, значить, вас не так цікавлять етапи перекладу, як який біт коду займає найбільше часу?
Даремно

2
Якщо ви використовуєте clang / llvm, ви можете застосувати подібний прийом, щоб відокремити фронт-енд (clang) від бекенда (llvm-opt). У задній частині ви навіть можете скинути графік оптимізатора та запустити їх окремо. У gcc можна порівняти час побудови між -O0 та -O3 та побачити різницю між часом, витраченим на оптимізацію, та часом, проведеним в інших місцях. Потім ви можете вибірково дозволити оптимізаторам побачити, хто є найгіршим порушником (якщо такий є).
Ze Blob

2

Можливо, ви зможете отримати деяку тягу з включеним варіантом strace -e trace=process -f -r -ttt -T, принаймні для компіляторів, таких як g ++, які розбиті на багато процесів.


0

Інші вже пропонували -ftime-report прапор командного рядка для GCC, що змушує компілятор надрукувати статистику про час, затрачений кожною фазою компіляції. Недоліком є ​​те, що він показує лише зведення для однієї одиниці.

Я написав сценарій Python , який дозволяє надрукувати загальний підсумок на всіх одиницях за кожною фазою компіляції, враховуючи файл журналу побудови проекту. Це також дозволяє сортувати за різними фазами. А також дозволяє порівняти два файли журналів (наприклад, якщо ви намагаєтеся зрозуміти вплив ваших змін).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.