Ускорение компиляции в Linux используя ccache и distcc

Тем кто использует такие операционные системы как Gentoo и FreeBSD пакеты и должны быть хорошо знакомы, те кто использует бинарные дистрибутивы так же могли о них слышать.

Ccache — кеш C/C++ компиляторов. При компилировании какого-либо файла вычисляется его хэш, если файл с таким хэшем есть в локальном кеше, то файл не будет повторно компилироваться, вместо этого будет использован файл из кеша. Так как при обновлении программы, как правило, изменяются не все файлы исходного кода, использование кеша позволяет существенно ускорить не только повторную компиляцию программы, но и ее обновлений.

Distcc — позволяет компилировать исходные коды C/C++/ObjC на нескольких компьютерах. Поддерживает кросс-платформенное компилирование. Для отсутствия ошибок в программ скомпилированных посредством distcc на всех компьютерах должна быть установлена одинаковая версия gcc, например 4.3.x, при этом x — может отличаться.

Рассмотрим установку и настройку ccache и distcc в бинарном дистрибутиве, на примере . Некоторые могут сказать, подобные программы в бинарном дистрибутиве не нужны, в общем то это справедливо, но только до тех пор, пока не требуется использование apt-build, make-kpkg и вас полностью устраивает набор ПО и их версий включенных в текущий релиз.

Пакеты ccache и distcc включены в стандартные репозитории Debian, поэтому их установка сводится к выполнению одной команды:

 [email protected]:~$ apt-get install ccache distcc 

Настройка Ccache

Чтобы начать использовать ccache во время компиляции нужно установить несколько переменных окружения, сделаем это через .profile или .bashrc, добавим такие строки:

 export PATH=/usr/lib/ccache:$PATH export CC="ccache gcc" export HOSTCC="ccache gcc" export HOSTCXX="ccache g++" export CCACHE_DIR="/var/cache/.ccache" 

Переменная CCACHE_DIR — устанавливает каталог где хранится кеш C/C++ компиляторов, по умолчанию она равна $HOME/.ccache.

Настройка Distcc

Данная будет полезна только тем у кого в распоряжении есть несколько компьютеров с одной версией gcc, например ПК и ноутбук, или ноутбук или домашний сервер.

Все настройки демона distcc в Debian находятся в файле /etc/default/distcc:

 STARTDISTCC="true" ALLOWEDNETS="127.0.0.1 192.168.0.0/24" LISTENER="0.0.0.0" JOBS="4" 

Число джобов не должно быть больше числа ядер:

 [email protected]:~$ cat /proc/cpuinfo |grep processor |wc -l 4 

Таким образом следует настроить distcc на каждом хосте. После настройки демонов их нужно запустить:

 [email protected]:~$ invoke-rc.d distcc start 

Теперь клиентская часть, в .profile или .bashrc, добавим:

 export CCACHE_PREFIX="distcc" export CONCURRENCY_LEVEL=7 export DISTCC_HOSTS="localhost/3 192.168.0.2/2 192.168.0.3/2" 

В переменной DISTCC_HOSTS указывается перечень хостов, через слеш указывается максимальное число параллельных задач компиляции которое может быть принято хостом, кроме того, если хост находится не в локальной сети, есть смысл включить lzo-компрессию. Для локальной машины стоит указать число задач на 1 меньше максимального, так как, кроме непосредственно процесса компиляции, она будет обрабатывать задачи отправляемые на удаленные хосты посредством distcc.
Переменная CONCURRENCY_LEVEL устанавливает максимальное число параллельных задач компиляции в момент времени.

На последок, немного практики, соберем ядро Linux 2.6.36 на копьютере с процессором Intel Atom D510:

 [email protected]:/usr/src/linux-2.6.36$ time make-kpkg --initrd --revision=atom1 kernel_image \ kernel_headers ... real 64m37.225s user 135m48.470s sys 27m38.509s 

Подчистим за собой

 [email protected]:/usr/src/linux-2.6.36$ make mrproper [email protected]:/usr/src/linux-2.6.36$ make-kpkg clean 

И соберем ядро еще раз:

 [email protected]:/usr/src/linux-2.6.36$ time make-kpkg --initrd --revision=atom1 kernel_image \ kernel_headers ... real 21m36.359s user 31m15.794s sys 12m5.879s 

Статистика ccache выглядит при этом примерно так:

 [email protected]:/usr/src/linux-2.6.36$ ccache -s cache directory /var/ccache/.ccache cache hit (direct) 17112 cache hit (preprocessed) 18 cache miss 8624 called for link 110 unsupported source language 117 unsupported compiler option 4494 no input file 4224 files in cache 25844 cache size 1.5 Gbytes max cache size 2.0 Gbytes