Формула турбореактивного прискорення прискорюємо компіляцію додатків за допомогою ccache і distcc

Збірка програм з вихідних процес для юніксоід звичайний і навіть звичайний. Ми компілюємо додатки, щоб випробувати новий функціонал, накласти патчі або просто встановити пакет в систему (привіт шанувальникам BSD і Gentoo). Однак сучасні програми настільки великі, що часом цей процес може зайняти не одну годину. Щоб не чекати так довго, пропоную скористатися спеціальними утилітами, які можуть істотно скоротити час збірки додатків.

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

export CFLAGS = '- O0'
export CXXFLAGS = $ CFLAGS

Користувачі FreeBSD і Gentoo можуть використовувати файл /etc/make.conf для зміни значення цих змінних:

У OpenBSD файл носить ім'я /etc/mk.conf.

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

У «класичних Лінукс» прапор '-j' слід вказувати прямо під час складання програми:

$ ./configure
$ Make -j5
$ Sudo make install

У системах, заснованих на портах, є спеціальні опції конфігураційного файлу, що дозволяють задіяти цей прапор глобально. Наприклад, в Gentoo будь опції make можна прописати в змінну MAKEOPTS файлу /etc/make.conf. Під FreeBSD ця змінна має ім'я MAKE_ARGS.

У тих же «source based» дистрибутивах можна задіяти інший трюк, що дозволяє скоротити час збірки в середньому на 10%. Сенс його в тому, щоб помістити каталог, який використовується для зберігання проміжних результатів компіляції, в tmpfs. Швидкість доступу до файлів істотно зросте, що і призведе до виграшу. Більшість систем використовує для зберігання тимчасових файлів один з підкаталогів / var / tmp, тому нам досить просто примонтировать до нього tmpfs. Приклад для Gentoo:

$ Sudo mount -t tmpfs tmpfs -o size = 1G, nr_inodes = 1M
/ Var / tmp / portage

Природно, машина повинна мати достатній обсяг пам'яті (2 Гб цілком вистачить), щоб tmpfs не почала використовувати swap, що ще більш розтягне процес компіляції. Якщо ж пам'яті в системі мало, то її можна звільнити за допомогою завершення всіх «товстих» додатків і виходу з іксів.

кешування

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

Програма ccache - це кешуючий препроцесор, який дозволяє уникнути повторної компіляції вже скомпільовані раніше файлів. Він генерує хеш для кожного компилируемого файлу, тому якщо з моменту попередньої компіляції файл залишається незмінним, його повторна обробка не проводиться, а використовується вже раніше скомпільований об'єктний файл. Ccache дозволяє істотно підняти швидкість повторної компіляції програми. У деяких випадках приріст може складати десятки разів.
Для залучення ccache досить встановити його в систему і запускати процес складання програми за допомогою приблизно такої команди:

$ CC = "ccache gcc" CXX = "ccache g ++" ./configure

Закешовану препроцесором об'єктні файли зберігаються в каталозі

/.ccache. За замовчуванням його розмір обмежений 1 Гб, але я б порекомендував збільшити його до 4 Гб:

Якщо місця в домашньому каталозі буде недостатньо для зберігання кешу, ти можеш вказати ccache використовувати інший каталог:

$ Echo "export CCACHE_DIR =" / var / tmp /
ccache / "" >>

Для вірності створи симлінк:

/.ccache
$ Ln -s / var / tmp / ccache

Особливе місце ccache займає в системах, заснованих на портах. Компіляція утиліт, необхідних тільки в процесі побудови порту, статичних бібліотек та інших «одноразових» інструментів, в таких системах зазвичай здійснюється кожен раз під час збирання порту, їх вимагає.

Тому ccache приносить неоціненну користь. До того ж, вже існуючі в кеші файли можуть бути повторно використані при оновленні портів. Нижче наводиться два рецепта використання ccache: в дистрибутиві Gentoo і в ОС FreeBSD.

Для активації ccache в Gentoo досить виконати два простих дії:

1. Встановити ccache:

$ Sudo emerge -av ccache

2. Відредагувати файл /etc/make.conf:

$ Sudo vi /etc/make.conf
# Активуємо ccache
FEATURES = "ccache"
# Місце зберігання кешу
CCACHE_DIR = "/ var / tmp / ccache /"
# Розмір кешу
CCACHE_SIZE = "4G"

Після виконання цих дій все порти будуть збиратися з використанням ccache. Щоб активувати ccache під час складання ядра за допомогою genkernel, слід використовувати наступну команду:

$ Sudo genkernel --kernel-cc = / usr / lib /
ccache / bin / gcc --menuconfig all

У випадку з FreeBSD все трохи складніше, але цілком в рамках розумного:

1. Встановлюємо ccache:

$ Cd / usr / ports / devel / ccache
$ Sudo make install clean

2. Редагуємо /etc/make.conf:

$ Sudo vi /etc/make.conf
# Якщо змінна оточення NO_CACHE НЕ
визначена, активуємо ccache
.if! defined (NO_CACHE)
CC = / usr / local / libexec / ccache / world-cc
CCX = / usr / local / libexec / ccache / world-c ++
.endif
# Відключаємо ccache при складанні самого себе
.if $
NO_CCACHE = yes
.endif

/.cshrc
# Стандартні змінні ccache
setenv PATH / usr / local / libexec / ccache: $ PATH
setenv CCACHE_PATH / usr / bin: / usr / local / bin
setenv CCACHE_DIR / var / tmp / ccache
setenv CCACHE_LOGFILE /var/log/ccache.log
# Встановлюємо розмір кешу
if (-x / usr / local / bin / ccache) then
/ Usr / local / bin / ccache -M 4G> / dev / null
endif

Для відключення ccache під час складання певного порту використовуємо таку команду замість стандартного «make install clean»:

$ Sudo make NO_CACHE = yes install clean

розподілена компіляція

Distcc - це обгортка для gcc, яка дозволяє задіяти потужності інших машин для збільшення швидкості компіляції програми. На відміну від інших рішень цього класу, distcc простий в установці і не вимагає модифікації вихідного коду програми або будь-яких підготовчих дій. На віддалену машину передається вже оброблений препроцесором вихідний код, тому зі свого боку вона не повинна мати будь-яких заголовних файлів або бібліотек для проведення успішної компіляції.

Кластер distcc зазвичай складається з одного клієнта і декількох серверів. Клієнт запускається на машині, яка ініціює процес складання, і передає завдання на виконання компіляції серверів, що працюють на віддалених машинах. Завдання складається з обробленого препроцесором файлу, що містить вихідний код, і прапорів компілятора. Все це відправляється на сервер за допомогою звичайного підключення до мережі без будь-якого шифрування і аутентифікації віддаленої сторони. Сервери, фактично виконують компіляцію, можуть працювати під управлінням операційних систем Linux, * BSD, Solaris або Windows (буде потрібно установка gcc і distcc в оточення cygwin), проте версія gcc на цих машинах повинна бути однаковою.

Немає сенсу використовувати distcc для одноразової збірки додатку, з цим цілком впорається і один комп. Зате в дистрибутиві Gentoo і ОС FreeBSD він може дати помітний приріст в швидкості установки і оновлення програм. Gentoo вже підготовлений для використання distcc, тому його власникам досить виконати кілька простих кроків для активації обгортки. Спочатку встановимо distcc на всі машини кластера:

$ Sudo emerge distcc

Далі переходимо на машину-клієнт і редагуємо файл /etc/make.conf:

$ Sudo vi /etc/make.conf
# Вказуємо кількість потоків компіляції
MAKEOPTS = "- j8"
# Активуємо distcc
FEATURES = "distcc"
# Каталог для зберігання кешу distcc
DISTCC_DIR = "/ tmp / .distcc"

В опції MAKEOPTS вказуємо загальна кількість потоків компіляції. Зазвичай це число вираховується наступним чином: загальна кількість процесорів / ядер на всіх машинах * 2 + 1. Однак це не завжди вірно, і, можливо, доведеться поекспериментувати, щоб підібрати оптимальне значення.

Для завдання хостів, що беруть участь в компіляції, скористаємося утилітою distcc-config (насправді, вона всього лише модифікує значення змінної DISTCC_HOSTS):

$ Sudo distcc-config --set-hosts "127.0.0.1
192.168.0.1 192.168.0.2 192.168.0.3 "

DISTCCD_OPTS = "$ -allow 192.168.0.0/24"

Тепер додамо сервер в дефолтовий рівень запуску і запустимо його:

$ Sudo rc-update add distccd default
$ Sudo /etc/init.d/distccd start

Тепер всі порти будуть компілюватися в кластері distcc. Щоб зібрати ядро ​​з використанням distcc, використовуй наступну команду:

$ Sudo genkernel --kernel-cc = distcc all

На відміну від Gentoo, FreeBSD не володіє інфраструктурою, необхідною для прозорого впровадження distcc, тому нам доведеться імплантувати його хірургічним шляхом. Для цього встановимо distcc за допомогою системи портів:

$ Cd / usr / ports / devel / distcc
$ Sudo make install clean

Це потрібно зробити на всіх машинах, які братимуть участь в процесі компіляції. Далі активуємо сервер distcc в /etc/rc.conf так, щоб він запускався під час ініціалізації ОС і міг приймати завдання від клієнта:

distccd_enable = "YES"
distccd_flags = "- nice 5 --allow 192.168.1.0/24
--daemon --user distcc -P /var/run/distccd.pid "

Цей крок також необхідно виконати на всіх машинах, включаючи клієнтську (щоб компіляція відбувалася і на машині, її ініціювала). Прапор '-allow' задає підмережа, машини якої мають право відправляти завдання сервера. Запускаємо сервер:

$ Sudo /usr/local/etc/rc.d/distccd start

Повертаємося на клієнтську машину. Відкриваємо файл /etc/make.conf і додаємо в нього наступні рядки:

# Vi /etc/make.conf
# Використовувати distcc як компілятора
CC = distcc
CXX = distcc
# Кількість завдань
MAKE_ARGS = - j8

Ми вказали distcc в змінних CC і CXX, завдяки чому порти і світ будуть автоматично збиратися в кластері, для розподілу збірки всього іншого підемо на невеликий трюк і підмінимо стандартні компілятори gcc і g ++:

# Mkdir -p / usr / local / lib / distcc / bin
# Cd / usr / local / lib / distcc / bin
# Ln -s / usr / local / bin / distcc gcc
# Ln -s / usr / local / bin / distcc g ++
# Ln -s / usr / local / bin / distcc cc
# Ln -s / usr / local / bin / distcc c ++

Відкриємо /root/.cshrc і помістимо створений нами каталог в початку шляхів пошуку бінарників:

setenv PATH / usr / local / lib / distcc / bin: $ PATH

setenv DISTCC_HOSTS "127.0.0.1 192.168.1.2
192.168.1.3 192.168.1.4 "

Все, для перевірки можна запустити збірку будь-якого порту. Пакет distcc поставляється разом з утилітою для моніторингу процесу складання distccmon-text. Запустивши програму без параметрів, ти побачиш на екрані поточний стан distcc. Щоб отримувати відомості в режимі реального часу, використовуй команду «distccmontext N», де N - це інтервал в секундах між виведенням інформації на екран. Користувачі Gnome (і не тільки) можуть скористатися графічним монітором під назвою distccmon-gnome.

Компіляція в хмарі

Програма distcc стає ефективним рішенням, коли мова заходить про збірку додатки в кластері машин, розміщених в локальній мережі, але в силу своєї незахищеності вона не може бути застосована для розподілу компіляції по машинам, розкиданим по всьому світу. Ти можеш створити приватну VPN, щоб обійти цю проблему, але я пропоную більш просте і ефективне рішення - SSH-тунель.

Всі наведені нижче інструкції актуальні для дистрибутива Gentoo, але не складе великих труднощів підігнати їх під інший дистрибутив / ОС.

# Mkdir -p /etc/distcc/.ssh
# Usermod -d / etc / distcc distcc

По-друге, йому повинен бути призначений шелл:

# Usermod -s / bin / bash distcc

По-третє, він повинен бути розлочили:

# Passwd -u distcc

Ці три кроки необхідно виконати на всіх машинах. Щоб клієнт міг логінитися на машини-робітники з використанням ssh і
віддавати завдання distcc, він повинен мати ключ:

# Ssh-keygen -t dsa -f /etc/distcc/.ssh/id_dsa

Публічний ключ (id_dsa.pub) необхідно скопіювати в каталог /etc/distcc/.ssh/authorized_keys всіх машин, які будуть брати участь в компіляції. Щоб ssh і portage змогли працювати спільно, доведеться виправити права доступу. На машинах-робітників виконуємо команди:

# Chown -R distcc: daemon / etc / distcc
# Chmod 644 /etc/distcc/.ssh/authorized_keys

На клієнті виконуємо команди:

# Chown portage: portage /etc/distcc/.ssh/id_dsa
# Chmod 600 /etc/distcc/.ssh/id_dsa
# Chmod 644 /etc/distcc/.ssh/id_dsa.pub

Щоб під час виконання emerge ssh не застряг на півдорозі з питанням про прийняття публічного ключа кожної машини-робітника, заздалегідь зберемо всі ці ключі:

# Ssh-keyscan -t rsa рабочій1 рабочій2 рабочій3 \
> /var/tmp/portage/.ssh/known_hosts
# Chown portage: portage /var/tmp/portage/.ssh/ \
known_hosts

Тепер створимо обгортку для distcc:

# Vi / etc / distcc / distcc-ssh
#! / Bin / bash
exec / usr / bin / ssh -i /etc/distcc/.ssh/id_dsa "$ @"

Зробимо її виконуваної:

# Chmod a + x / etc / distcc / distcc-ssh

Відредагуємо файл /etc/make.conf:

# Vi /etc/make.conf
MAKEOPTS = "- j8"
FEATURES = "distcc"
DISTCC_SSH = "/ etc / distcc / distcc-ssh"
DISTCC_HOSTS = "localhost / 2 distcc @ рабочій1 / 3 distcc @
рабочій2 / 5 "

вдалою компіляції

Такі програми, як ccache і distcc, укупі з іншими трюками, можуть дати досить істотний приріст в швидкості збирання, проте ти повинен мати на увазі, що не всі програми можуть бути зібрані з їх допомогою. Збірка деяких складних програм, що складаються з багатьох компонентів, часто завершується помилкою, причину якої важко ідентифікувати. Тому будь уважний, використовуй останню версію ccache і однакові версії gcc на машинах distcc-кластера, крім того, не забувай заглядати в файл INSTALL.

  • У дистрибутиві Gentoo різні прапори компіляції портів можна активувати індивідуально для кожного порту (див. Файл / etc / portage / package. Cflags). Це можна використовувати для примусового відключення ccache і distcc при складанні певних портів.
  • Присвоївши опції PORTAGE_NICENESS файлу / etc / make. conf в дистрибутиві Gentoo занадто велике значення, ти можеш власноруч сильно уповільнити швидкість збірки додатків.
  • Програми ccache і distcc відмінно уживаються разом. У Gentoo ти можеш активувати їх одночасно, додавши рядок FEATURES = "ccache distcc" в файл /etc/make.conf.

Покажи цю статтю друзям: