Обычно g++ при компиляции намного медленнее, чем gcc?

Последние несколько месяцев я программировал на простом C из-за нашей университетской программы. Программы, которые я пишу, довольно маленькие и очень нетребовательны к ресурсам. В результате компиляция с помощью gcc всегда была почти мгновенным процессом (40 мс в моей «самой большой» программе на данный момент).

Однако недавно я принял участие в местном конкурсе, для которого C++, очевидно, является нормой, и начал практиковаться. Несмотря на то, что мои программы по-прежнему очень малы (не более половины КБ), я заметил, что компиляция с помощью g++ постоянно была почти как пауза в 0,2 секунды, за которой следовала мгновенная компиляция, к которой я привык с помощью gcc.

Вот код, на котором я сейчас его тестирую:

//#include <bits/stdc++.h> // I commented this out thinking that maybe the problem was due to too many header files being included
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std; // I know this is kind of a bad practice but I've been told it's recommended in competitions for ease of writing

int mex(vector<int> arr, vector<int> subarr) {
    int min = INT_MAX;

    for (auto i : arr) {
        // If i doesn't exist in subarr
        if (find(subarr.begin(), subarr.end(), i) == subarr.end()) {
            if (i < min) {
                min = i;
            }
        }
    }

    return min;
}

int main () {
    vector<int> a = {0,1,2,3,4,5};
    vector<int> suba = {0, 1,3,4};

    cout << mex(a, suba) << endl;

    return 0;
}

Это компилируется за 240 мс. Вот g++ ftime-report:

Time variable                                   usr           sys          wall           GGC
 phase setup                        :   0.00 (  0%)   0.00 (  0%)   0.00 (  0%)  1562k (  2%)
 phase parsing                      :   0.16 ( 84%)   0.13 ( 87%)   0.29 ( 85%)    60M ( 83%)
 phase lang. deferred               :   0.01 (  5%)   0.01 (  7%)   0.02 (  6%)  5818k (  8%)
 phase opt and generate             :   0.02 ( 11%)   0.01 (  7%)   0.03 (  9%)  5468k (  7%)
 |name lookup                       :   0.05 ( 26%)   0.02 ( 13%)   0.03 (  9%)  2550k (  3%)
 |overload resolution               :   0.01 (  5%)   0.00 (  0%)   0.02 (  6%)  6891k (  9%)
 callgraph construction             :   0.01 (  5%)   0.00 (  0%)   0.01 (  3%)  1448k (  2%)
 df scan insns                      :   0.01 (  5%)   0.00 (  0%)   0.00 (  0%)  4128  (  0%)
 preprocessing                      :   0.01 (  5%)   0.05 ( 33%)   0.05 ( 15%)  1805k (  2%)
 parser (global)                    :   0.03 ( 16%)   0.02 ( 13%)   0.07 ( 21%)    16M ( 23%)
 parser struct body                 :   0.00 (  0%)   0.03 ( 20%)   0.03 (  9%)    11M ( 15%)
 parser function body               :   0.03 ( 16%)   0.00 (  0%)   0.03 (  9%)  3231k (  4%)
 parser inl. func. body             :   0.01 (  5%)   0.02 ( 13%)   0.01 (  3%)  1474k (  2%)
 parser inl. meth. body             :   0.01 (  5%)   0.00 (  0%)   0.03 (  9%)  5790k (  8%)
 template instantiation             :   0.07 ( 37%)   0.02 ( 13%)   0.08 ( 24%)    19M ( 27%)
 constant expression evaluation     :   0.00 (  0%)   0.00 (  0%)   0.01 (  3%)    85k (  0%)
 expand                             :   0.00 (  0%)   0.01 (  7%)   0.00 (  0%)   367k (  0%)
 integrated RA                      :   0.00 (  0%)   0.00 (  0%)   0.00 (  0%)  2092k (  3%)
 LRA non-specific                   :   0.00 (  0%)   0.00 (  0%)   0.01 (  3%)    14k (  0%)
 symout                             :   0.01 (  5%)   0.00 (  0%)   0.00 (  0%)  6907k (  9%)
 rest of compilation                :   0.00 (  0%)   0.00 (  0%)   0.01 (  3%)   212k (  0%)
 TOTAL                              :   0.19          0.15          0.34           73M

Я использую версии gcc и g++ 11.4.0 в Ubuntu 22.04.

Это нормальное явление? Обычно g++ заметно медленнее, чем gcc? Или у меня на компьютере какая-то проблема?

Прошло много времени с тех пор, как я играл с этим, но IIRC, компиляция C++ была в основном затруднена из-за огромных включаемых файлов STL, а не из-за того, что C++ был намного медленнее (хотя это было немного медленнее, понятное дело) .

Petr Skocik 28.02.2024 22:07

Средний заголовок включения C++ увеличивает время компиляции гораздо больше, чем средний заголовок включения POSIX/стандарта C. Заголовки C также могут замедлять компиляцию, особенно если они содержат много встроенных функций (макросы анализируются намного быстрее, чем встроенные функции). Но заголовки POSIX/standard-C обычно представляют собой всего лишь несколько определений типов и объявлений с редким #define.

Petr Skocik 28.02.2024 22:11

Вероятно, вы можете ускорить локальную компиляцию, включив все стандартные заголовки в отдельный файл в виде предварительно скомпилированного заголовка . Вы по-прежнему можете сделать свой код доступным для отправки, используя какой-либо макрос, который вы определяете локально. Если он не определен, не используйте предварительно скомпилированный заголовок, а вместо этого включите все встроенное в основной исходный файл.

paddy 28.02.2024 22:16
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
134
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Да, это нормально. Язык C++ намного сложнее, чем язык C, и в стандартных заголовках содержится больше возможностей.

Создание проектов корпоративного уровня может занять несколько часов, так что будьте очень рады, что ваш проект займет всего 0,2 секунды!

Ответ принят как подходящий

Да, по моему опыту, это довольно распространенное явление, поскольку C++ имеет множество функций и более сложный синтаксис.

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

Более подробное объяснение причины вы можете найти здесь

Теоретически, C должен иметь преимущество в скорости синтаксического анализа, поскольку в отличие от C++ у него почти контекстно-свободная грамматика. На практике скорости синтаксического анализа очень похожи (C++ лишь на несколько процентов медленнее), а реальная проблема — большие (раздутые) заголовки со множеством встроенных функций в STL.

Компиляции C также могут замедляться из-за заголовков со многими встроенными функциями (в меньшей степени из-за макросов), но на практике их не так много, по крайней мере, в обычных.

В Linux вы можете включить все заголовки posix одновременно, затратив время компиляции в несколько десятков мс (незаметно для человека) для всех из них вместе. По сравнению с этим, один заголовок STL может легко добавить сотни мс ко времени компиляции одного файла (заметная задержка).

Вот небольшой bash-скрипт с некоторой информацией (создает/удаляет файлы в текущем каталоге!!):

#!/bin/bash -eu
for i in {0..1000}; do echo "int f$i(void){return $i;}"; done > funcs.c
for i in {0..1000}; do echo "static inline int i$i(void){return $i;}"; done > inls.c
for i in {0..1000}; do echo "#define M$i() $i"; done > macs.c
echo " " > empty.c
echo "#include <vector>" > incl_vector.cc
echo "#include <string>" > incl_string.cc
echo "#include <iostream>" > incl_iostream.cc
echo "#include <string.h>" > incl_string.c
echo "#include <stdio.h>" > incl_stdio.c


TIMEFORMAT=%Rs
: ${CC:=gcc}
set -x
time $CC -xc -Os empty.c -c
time $CC -xc -Os funcs.c -c
time $CC -xc -Os inls.c -c
time $CC -xc -Os macs.c -c
time $CC -xc -Os incl_string.c -c
time $CC -xc -Os incl_stdio.c -c

time $CC -xc++ -Os empty.c -c
time $CC -xc++ -Os funcs.c -c
time $CC -xc++ -Os inls.c -c
time $CC -xc++ -Os macs.c -c
time $CC -xc++ -Os incl_vector.cc -c
time $CC -xc++ -Os incl_string.cc -c
time $CC -xc++ -Os incl_iostream.cc -c

Я получаю (более старая машина (Sandy Bridge i7) с gcc-13):

+ gcc -xc -Os empty.c -c
0.015s
+ gcc -xc -Os funcs.c -c
0.808s
+ gcc -xc -Os inls.c -c
0.031s
+ gcc -xc -Os macs.c -c
0.015s
+ gcc -xc -Os incl_string.c -c
0.017s
+ gcc -xc -Os incl_stdio.c -c
0.020s
+ gcc -xc++ -Os empty.c -c
0.015s
+ gcc -xc++ -Os funcs.c -c
0.860s
+ gcc -xc++ -Os inls.c -c
0.041s
+ gcc -xc++ -Os macs.c -c
0.016s
+ gcc -xc++ -Os incl_vector.cc -c
0.188s
+ gcc -xc++ -Os incl_string.cc -c
0.290s
+ gcc -xc++ -Os incl_iostream.cc -c
0.408s

и очень похожие цифры и относительные различия для лязга.

Другие вопросы по теме