Почему компиляция занимает так много времени?

Я разрабатываю язык программирования, и одна из проблем, о которых я думал, заключалась в том, почему языки программирования долго компилируются. Предполагается, что C ++ занимает много времени, потому что ему необходимо анализировать и компилировать заголовок каждый раз, когда он компилирует файл. Но я-слышал-, предварительно скомпилированные заголовки занимают столько же времени? Я подозреваю, что С ++ - не единственный язык, у которого есть эта проблема.


person Community    schedule 26.02.2009    source источник


Ответы (8)


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

person dsimcha    schedule 26.02.2009

Компиляция - это сложный процесс, который состоит из нескольких шагов:

  • Сканирование / Lexing
  • Парсинг
  • Генерация промежуточного кода
  • Возможна промежуточная оптимизация кода
  • Генерация кода целевой машины
  • Опционально Машинно-зависимая оптимизация кода

(Оставляя в стороне ссылки.)

Естественно, для более длинных программ это займет некоторое время.

person Rob Lachlan    schedule 26.02.2009
comment
Это совсем не объясняет, почему любой компилятор Pascal (например) на несколько порядков быстрее любого компилятора C ++. - person hmijail mourns resignees; 23.10.2020

Предварительно скомпилированные заголовки работают намного быстрее, как это было известно по крайней мере с 1988 года.

Обычная причина того, что компилятор C или компилятор C ++ занимает много времени, заключается в том, что он должен #include, предварительно обработать, а затем lex gazillions токенов.

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

gcc -O использует очень эффективный, но несколько медленный метод оптимизации, разработанный Крисом Фрейзером и Джеком Дэвидсоном. Большинство других оптимизаторов могут работать медленно, потому что они требуют повторения итераций над довольно большими структурами данных.

person Norman Ramsey    schedule 26.02.2009
comment
Было бы справедливо сказать, что попытка вложить много интеллекта в оптимизацию - верный способ добиться длительного времени компиляции? Это было мое случайное понимание, но я не хочу делать общих заявлений ... - person dmckee --- ex-moderator kitten; 26.02.2009
comment
Почему нельзя повторно использовать оптимизацию из предыдущей компиляции, когда изменилась только часть кода? Или, если это можно сделать, то как? - person HopefullyHelpful; 14.03.2017

Дизайн языка действительно влияет на производительность компилятора. Компиляторы C ++ обычно медленнее, чем компиляторы C #, что во многом связано с дизайном языка. (Это также зависит от разработчика компилятора, Андерса Хейлсберга реализовал C # и является одним из лучших. )

Упрощенная структура «заголовочного файла» C ++ способствует его более низкой производительности, хотя предварительно скомпилированные заголовки часто могут помочь. C ++ - гораздо более сложный язык, чем C, поэтому компиляторы C обычно быстрее.

person Greg Hewgill    schedule 26.02.2009
comment
Вы уверены, что Андерс участвовал в реализации компилятора? Я думал, что он был более вовлечен с точки зрения высокого уровня, а не в коде компилятора, но это всего лишь предположение с моей стороны. - person tsimon; 26.02.2009
comment
Я был бы удивлен, если бы он не участвовал хотя бы в части фактической реализации, но я не знаю наверняка. Хотя он определенно участвует в языковом дизайне. - person Greg Hewgill; 26.02.2009
comment
На ум приходят Delphi и Python как исключительно быстрые компиляторы ... - person Arafangion; 26.02.2009
comment
Андерс также был главным инженером Delphi (а до этого - Turbo Pascal). - person Greg Hewgill; 02.03.2009

Компиляция не требует много времени: tcc компилирует ANSI c достаточно быстро, чтобы быть полезным как переводчик.

Что-то думать о:

  1. Сложность в сканировании и парсинге проходит. По-видимому, повредит необходимость долгого просмотра вперед, как и контекстные (в отличие от контекстно-свободных) языков.
  2. Внутреннее представительство. Создание и работа над большим и функциональным AST займет некоторое время. Предположительно, вам следует использовать простейшее внутреннее представление, которое будет поддерживать функции, которые вы хотите реализовать.
  3. Оптимизация. Оптимизация - дело суетливое. Вам нужно проверить множество различных условий. Вероятно, вы захотите сделать несколько проходов. На все это потребуется время.
person dmckee --- ex-moderator kitten    schedule 26.02.2009

Они занимают столько времени, сколько нужно, и обычно это зависит от того, сколько постороннего материала вы вводите в свои единицы компиляции. Я бы хотел увидеть, как вы скомпилируете их вручную как можно быстрее :-)

В первый раз, когда вы компилируете файл, у вас не должно быть заголовков вообще. Затем добавляйте их по мере необходимости (и, когда закончите, проверьте, нужны ли они вам).

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

Некоторые компиляторы (на самом деле IDE) выполняют инкрементную компиляцию в фоновом режиме, так что они (почти) всегда близки к полностью скомпилированным.

person paxdiablo    schedule 26.02.2009
comment
++ для меньших единиц компилятора - person Thilo; 26.02.2009

Я думаю, что в других ответах здесь пропущены некоторые важные части ситуации, которые замедляют компиляцию C ++:

  • Модель компиляции, которая сохраняет _1 _ / _ 2_ файлы на диск, считывает их обратно, а затем связывает их
  • Связывание в целом и плохие медленные линкеры в частности
  • Чрезмерно сложный препроцессор макросов
  • Произвольно сложная система шаблонов, полная по Тьюрингу
  • Вложенное и многократное включение исходных файлов, даже с #pragma once
  • Фрагментация, вызываемая пользователем, разбиение кода на слишком много файлов (даже до одной функции для каждого файла, в крайнем случае)
  • Раздутые или не требующие больших усилий внутренние структуры данных в компиляторе
  • Раздутая стандартная библиотека, злоупотребление шаблонами

Напротив, это не замедляет компиляцию C ++:

  • Сканирование / Lexing
  • Парсинг
  • Генерация промежуточного кода
  • Генерация целевого машинного кода

Кстати, оптимизация - одно из самых больших замедлений, но это единственное замедление, которое действительно необходимо в некоторой степени, а также совершенно необязательно.

person pmttavara    schedule 18.02.2018
comment
Создается впечатление, что это ошибка пользователя и разработчика компилятора в том, что C ++ медленно компилируется. Это не; C ++ и C, как известно, плохо справляются с этим (отсутствием) дизайна. Вот почему, например, дизайн Go делает упор на целенаправленную быструю компиляцию. - person hmijail mourns resignees; 23.10.2020

Запустите Idera RAD Studio (есть бесплатная версия). Он поставляется с C ++ и Delphi. Код Delphi компилируется за крошечную долю времени, по сравнению с кодом C ++, выполняющим то же самое. Это связано с тем, что C ++ ужасно эволюционировал на протяжении десятилетий, не уделяя особого внимания последствиям компилятора для его сложных макросов, определяемых контекстом, и, в некоторой степени, так называемого адского ".hpp". У Ada похожие проблемы. Диалект Delphi Паскаля был разработан с нуля, чтобы быть эффективным языком для компиляции. Таким образом, компилятор и запуск занимают секунды, а не минуты, что делает итеративную отладку быстрой и простой. Отладка медленно компилируемых языков - огромная трата времени, и вы знаете что! Кстати, Андерс также написал Delphi до того, как M $ украл его!

person Steven Bliss    schedule 12.08.2019