2015-05-10 2 views
1

Я пишу компилятор, который генерирует код C++ в конце. В настоящее время я задаюсь вопросом, что быстрее компилируется.Что можно скомпилировать быстрее? Источник и заголовок для каждого метода или что-либо в одном файле?

Первые заметки о составителя:

  1. У меня нет каких-либо классов \ структур, они оптимизированы внутри функций.
  2. Я не имею ничего такого, как #include <vector>, когда мне нужно использовать такие функции, как printf, из библиотек, тогда я вручную разместил прототип. (Составитель сделать это вручную.)

У меня есть два варианта:

Вариант # 1:

//.h 
#include "A.h" 
#include "B.h" 

int function(/* parameters */); 
//.cpp 
int function(/* parameters */) { 
    // code 
} 

Каждая функция имеет собственный источник и заголовок. Преимущества:

  1. Я могу сделать компилятор комментариями, включающими в себя файл, который включен перед ним. Например, если содержимое #include "B.h" включено в #include "A.h", тогда я могу прокомментировать строку #include "B.h". (Сохраняет чтение файлов.)
  2. Я могу распознать неизменные методы/функции/файлы (когда я регенерирую свой код, и он может находить точные файлы из ранее.) И перерабатывать их объектные файлы. (Сохраняет объект компиляции.)

Вариант № 2:

int function(/* parameters */); 
int function2(/* parameters */); 
int function3(/* parameters */); 
// ... 
int function(/* parameters */) { 
    // code 
} 
// ... 

Все функции сразу определены (эти прототипы в верхней части) и составил в этом одном файле.

Преимущества:

  1. Single последовательного чтения с диска. (Нет иерархии включения и множественного включения из разных объектов.)
  2. Отдельный объект для компиляции, исключая библиотеки.

На одном взгляде выглядит как вариант # 1 быстрее, но некоторые люди говорят, что они попробовали второй, и это дало их проекту импульс в компиляции времени. Они не сравнили оба варианта и не дали никаких доказательств.

Могу ли я получить объяснение, для которого быстрее, чем контрольных?

+2

Бенчмарк и узнать. Все остальное - это в основном спекуляция. –

+0

@ColonelThirtyTwo Я уверен, что кто-то может «дать слово», но почему опция быстрее, чем другая, а не только эталон. – LyingOnTheSky

+0

вариант 3: реализовать [модули] (http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4214.pdf) – bolov

ответ

2

С ++, как известно, медленно быть составлен, в частности, потому, что заголовки стандарт C++ (например, <vector>, <map> или другие стандартные контейнеры) приносят в много кода C++ (и жетонов) через внутренних заголовков.

Созданы ли ваши машины #include -d, или все они являются общими для вашей среды выполнения?Вы можете подумать о том, чтобы иметь один заголовок и предварительно скомпилировать его (при условии, что последний GCC или Clang/LLVM), см. this. Тогда вам нужно иметь только один #include в верхней части каждого сгенерированного файла C++.

BTW, я не уверен, что C++ - хороший целевой язык для некоторого компилятора. Создание кода на C (возможно, с использованием Boehm's GC, например Bigloo), вероятно, более актуально. Генерирование кода на C++ имеет смысл, если вы хотите вписаться в какой-либо существующий API, например, я делаю в MELT, встраиваясь в внутренние элементы GCC, а затем я не генерирую много кода с использованием стандартных шаблонов C++.

Наконец, когда вы создаете C (и даже больше при создании подлинного C++), вы действительно хотите, чтобы компилятор C или C++ оптимизировал сгенерированный код на C или C++. Время анализа сгенерированного кода не имеет значения, чем много (вы можете попробовать -freport-time вариант для измерения, где g++ требуется время). Новый GCC 5.1 имеет libgccjit, который может вас заинтересовать.

+0

Это все равно устранит повторное включение заголовков в разные '.cpp', но это не исключает необходимости связывать большое количество объектов. – LyingOnTheSky

2

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

Балансировочная сила, как указано, является начальной стоимостью каждой компиляции. У вас есть несколько ядер процессора, которые несут одну и ту же стоимость запуска.

В результате распараллеливание перестает быть выигрышем при добавлении дополнительного блока переводов, что требует дополнительных накладных расходов, чем вы сохраняете, используя это дополнительное ядро.

+0

Но после этого вам нужно соединить все те объекты, которые вы скомпилировали, что вы не можете сделать параллельно. Я думаю, что один большой объект сделает связь быстрее. (?) Я начинаю думать, что здесь поможет только эталон. – LyingOnTheSky

+0

@LyingOnTheSky: Современные линкеры используют связь на уровне функций, так как один большой объект все еще содержит столько функций. – MSalters

Смежные вопросы