GCC и большой исходник
От: koenjihyakkei Россия  
Дата: 31.08.15 22:04
Оценка:
Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб? Сейчас проблема в том, что съедается вся оперативка — 16Гб, а компиляция так до конца и не доходит. Сейчас проблена рещается тем, что файл полностью не генерится, генерится только около 7000 строк (против полных 350000) и все нормально отрабатывает.

Файл исходника — автогенеренные юнит тесты, код примерно такой:
void RunTests()
{
    Test test;

    test.fn(..)
    test.fn2(..)
    // еще порядка 8-10 вызовов функций

    // следующий кейс, примерно то же самое, 8-10 вызовов методов класса Test
    test.fn(..)
    test.fn2(..)

    // и так далее на 365000 строк
}
Отредактировано 31.08.2015 23:06 koenjihyakkei . Предыдущая версия .
Re: GCC и большой исходник
От: Sni4ok  
Дата: 31.08.15 22:07
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб? Сейчас проблема в том, что съедается вся оперативка — 16Гб, а компиляция так до конца и не доходит.


а в чём заключается боль? можете памяти докупить, можете автогенерированный код отрефакторить, можете свап побольше сделать.
Re: GCC и большой исходник
От: smeeld  
Дата: 31.08.15 22:36
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб? Сейчас проблема в том, что съедается вся оперативка — 16Гб, а компиляция так до конца и не доходит.


Что за на? Как же он кернель компилит?
Re: GCC и большой исходник
От: Kernighan СССР  
Дата: 31.08.15 22:40
Оценка: 4 (1)
Здравствуйте, koenjihyakkei, Вы писали:

K>Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб? Сейчас проблема в том, что съедается вся оперативка — 16Гб, а компиляция так до конца и не доходит.


Чё-то слишком много он у тебя памяти жрёт. На первый взгляд там у тебя какая-то засада. Например файл сам себя инклюдит.
Re[2]: GCC и большой исходник
От: koenjihyakkei Россия  
Дата: 31.08.15 23:27
Оценка:
Здравствуйте, Kernighan, Вы писали:

K>Чё-то слишком много он у тебя памяти жрёт. На первый взгляд там у тебя какая-то засада. Например файл сам себя инклюдит.


Сам себя не инклюдит, в первом сообщении дописал. Единственное на что сейчас грешу, это то что для каждого кейса создается по одному-два локального экземпляра другого класса, возможно локальный стек все и сжирает..
Вот код поподробнее
};
class Item {
    // ...
    Item& add1() { ... return *this; }
    Item& add2() { ... return *this; }
}

class Test {
    Item create() {
    // ...
    return *m_item;
    }
}

// используется примерно так
test.create().add1().add1().add2(); // произвольное количество вызовов функций
// и так далее более 47842 раз
test.create().add1().add1().add2();


По идее компилятор должен понять, что не надо под каждый такой Item выделять место в стеке, но такое ощущение, что именно это он и делает.
Отредактировано 31.08.2015 23:29 koenjihyakkei . Предыдущая версия . Еще …
Отредактировано 31.08.2015 23:28 koenjihyakkei . Предыдущая версия .
Re[2]: GCC и большой исходник
От: Ops Россия  
Дата: 01.09.15 00:22
Оценка:
Здравствуйте, smeeld, Вы писали:

S>Что за на? Как же он кернель компилит?


А где там 1 большой файл?
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[3]: GCC и большой исходник
От: ArtDenis Россия  
Дата: 01.09.15 03:30
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>По идее компилятор должен понять, что не надо под каждый такой Item выделять место в стеке, но такое ощущение, что именно это он и делает.


Я не понял какая связь между

а компиляция так до конца и не доходит

и

По идее компилятор должен понять, что не надо под каждый такой Item выделять место в стеке, но такое ощущение, что именно это он и делает.


[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re[4]: GCC и большой исходник
От: koenjihyakkei Россия  
Дата: 01.09.15 04:11
Оценка:
Здравствуйте, ArtDenis, Вы писали:

AD>Здравствуйте, koenjihyakkei, Вы писали:


K>>По идее компилятор должен понять, что не надо под каждый такой Item выделять место в стеке, но такое ощущение, что именно это он и делает.


AD>Я не понял какая связь между


AD>

AD>а компиляция так до конца и не доходит


Не доходит — в смысле я прерываю компиляцию, ибо резко начинает жрать память =загружает всю оперативку и начинает своп юзать, а когда она завершится непонятно.

AD>и

AD>

AD>По идее компилятор должен понять, что не надо под каждый такой Item выделять место в стеке, но такое ощущение, что именно это он и делает.


Ну написал же, что в одной функции более 47842 раз вызывается функция, которая создает временный объект. Но сейчас я уже проверил эту теорию, переписав функцию, чтобы она возвращала ссылку, а не копию... не помогло.

AD>


Вот и я о том же
Re[3]: GCC и большой исходник
От: smeeld  
Дата: 01.09.15 06:51
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>А где там 1 большой файл?


А где у ТС сказано, что исходник в виде одного файла? Зачем такие непотребства
творить?
Re[4]: GCC и большой исходник
От: koenjihyakkei Россия  
Дата: 01.09.15 07:05
Оценка:
Здравствуйте, smeeld, Вы писали:

S>А где у ТС сказано, что исходник в виде одного файла?


Ну, например, в самом слове "исходник", который в единственном числе.

S>Зачем такие непотребства творить?


Ну что мне всю проблематику рассказывать сложившейся ситуации? Ну нет еще функциональных тестов, нету. Только в процессе и непонятно, когда будут готовы, а юнит-тестами можно уже сейчас все покрыть и отловить все основные баги. Проблема лишь в том, что я описал в топике.
Разбивать файл на несколько исходников и модифицировать билд файлы не вариант.
Отредактировано 01.09.2015 7:09 koenjihyakkei . Предыдущая версия .
Re: GCC и большой исходник
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.09.15 07:24
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб? Сейчас проблема в том, что съедается вся оперативка — 16Гб, а компиляция так до конца и не доходит. Сейчас проблена рещается тем, что файл полностью не генерится, генерится только около 7000 строк (против полных 350000) и все нормально отрабатывает.


K>Файл исходника — автогенеренные юнит тесты, код примерно такой:


Поставьте этому файлу -O0. Оптимизация такому файлу нафиг не сдалась, а именно она жрёт ресурсы.
The God is real, unless declared integer.
Re: GCC и большой исходник
От: fin_81  
Дата: 01.09.15 07:35
Оценка: +1
Слишком много инклудов, скорее всего, инклудов с шаблонными классами. Какого размера файл после препроцессора (gcc -E)?
Re: GCC и большой исходник
От: ELazin http://rsdn.ru/forum/prj/6225353.1
Автор: ELazin
Дата: 26.10.15
Дата: 01.09.15 08:55
Оценка: -1
K>Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб?

Полагаю что нет. Компилятор должен загрузить твой исходник полностью, распарсить его (AST компилятора явно займет больше места в памяти чем сам исходник). Наверняка линковка тоже не быстро происходит. Вряд ли это тот случай, под который оптимизировали GCC.

Я предлагаю:
— разбить исходник на несколько единиц трансляции, два десятка cpp-шек по ~1Мб будут компилироваться быстрее
— сделать так, чтобы большинство символов в исходников имели внутреннее связывание (internal linkage)
Re: GCC и большой исходник
От: Evgeny.Panasyuk Россия  
Дата: 01.09.15 09:08
Оценка: 20 (1) +2
Здравствуйте, koenjihyakkei, Вы писали:

K>Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб? Сейчас проблема в том, что съедается вся оперативка — 16Гб, а компиляция так до конца и не доходит. Сейчас проблена рещается тем, что файл полностью не генерится, генерится только около 7000 строк (против полных 350000) и все нормально отрабатывает.


Сталкивался с подобной проблемой на разных компиляторах, как раз при генерируемом коде. Обычно дело не просто в большом translation unit (что, учитывая includes, и вовсе не редкость), а в большом объёме кода в одной из функций.
Решается это либо распилом этой функции на несколько, либо заменой кода на данные, что предпочтительней.
Например в коде функции foo десять тысяч вызовов функции bar с разными аргументами. Делаем массив наборов аргументов, а десять тысяч вызовов заменяем пробежкой по массиву однострочным циклом. Такой код компилируется на порядки быстрее, и дешевле по ресурсам.
Re[2]: GCC и большой исходник
От: Evgeny.Panasyuk Россия  
Дата: 01.09.15 09:35
Оценка: +1
Здравствуйте, ELazin, Вы писали:

EL>Я предлагаю:

EL>- разбить исходник на несколько единиц трансляции, два десятка cpp-шек по ~1Мб будут компилироваться быстрее

Большие TU обычно сами по себе проблемой не являются. Более того, тысяча файлов собранные в десяток TU может компилироваться даже быстрее (есть реальный опыт ускорения в разы) — смотри Unity Builds.

Проблемой обычно являются функции с большими телами, а конкретно с большим количеством statements. В таких случаях вылезает нелинейная зависимость (что-то типа квадратичной) затрат времени/ресурсов компиляции от количества statements. Вероятно это как-то связанно с оптимизацией — типа компилятор пытается целиком прожевать весь заинлайненный код.

Подобные большие функции обычно появляются при кодогенерации и рассуждениях типа "ну и что что убогая копипаста, она же генерируется".
Генерировать же, по моим представлениям, нужно где-то на грани необходимого минимума — данные, структуры, обвязки необходимые для reflection, плюс те места, которые без генерации получаются чрезмерно сложными.
Сам по себе код генерирующий другой код — он сложнее обычного, его труднее поддерживать, неудобно с ним работать и т.д. и т.п. Нужно стараться его избегать, но естественно НЕ ценой копипасты.
Re: GCC и большой исходник
От: Кодт Россия  
Дата: 01.09.15 11:28
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Файл исходника — автогенеренные юнит тесты


Если можно автогенерённые тесты оформить в виде параметрических тестов, — то, наверное, следует это сделать.
В зависимости от фреймворка, конкретная техника может отличаться.
Но, в конце концов, хотя бы так
void run() {
  for(i : ......) {
    Test t;
    if(i & 1) { ..... }
    if(i & 2) { ..... }
    if(i & 4) { ..... }
  }
}

или так
void run_one(Test&& t) {
  t.f1();
  t.f2();
  .....
}

void run() {
  run_one( Test(1) );
  run_one( Test(2) );
  run_one( Test(3) );
  .....
}

В любом случае, нужно разбить одну большую функцию на подфункции, потому что иначе там со стеком бог знает что творится. Конечно, гусь пытается рассовать временные переменные по регистрам и слотам стекового кадра, и тратит на это кучу сил.
Перекуём баги на фичи!
Re[2]: GCC и большой исходник
От: alex19  
Дата: 01.09.15 14:10
Оценка:
> иначе там со стеком бог знает что творится.

В этой ветке уже несколько раз упоминали стек, а я до сих пор не понимаю причем тут он. У ТС не проходит компиляция. До выполнения exe'шника дело не доходит. Причем тут работа со стеком во время компиляции?
Re[3]: GCC и большой исходник
От: Кодт Россия  
Дата: 01.09.15 14:24
Оценка:
Здравствуйте, alex19, Вы писали:

A>В этой ветке уже несколько раз упоминали стек, а я до сих пор не понимаю причем тут он. У ТС не проходит компиляция. До выполнения exe'шника дело не доходит. Причем тут работа со стеком во время компиляции?


При том, что компилятор должен рассовать стопятьсот локальных переменных, дав им уникальные смещения в кадре стека, а заодно определив стратегию подгрузки в регистры.
Если включить оптимизацию, то задача внезапно из линейной может стать квадратичной как по времени, так и по памяти.
Перекуём баги на фичи!
Re: GCC и большой исходник
От: MT-Wizard Украина  
Дата: 02.09.15 06:02
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Есть ли возможность безболезненно скормить GCC больщой исходник, около 17Мб? Сейчас проблема в том, что съедается вся оперативка — 16Гб, а компиляция так до конца и не доходит. Сейчас проблена рещается тем, что файл полностью не генерится, генерится только около 7000 строк (против полных 350000) и все нормально отрабатывает.


1. Компилится ли с -O0?
2. Если да — варианты: всегда компилить без оптимизации, или же индивидуальными ключами отключать разные оптимизации (пока не найдётся виновная)
3. Если нет — ой, оно даже не парсится, только упрощать генерируемую функцию.

Ну и, как уже тут упоминалось, при оптимизации больше всего проблем вызывают большие функции — так как функция является единицей работы оптимизатора, практически всё считается для неё. А если там ещё и здоровые basic block (куча кода без ветвлений) — пиши пропало. Потому можно просто попробовать поставить лимит генерации по количеству операторов в функции, дальше создавать новую.
А ти, москалику, вже приїхав (с)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.