
Стандартом для компиляции C/C++ кода в *nix - системах долгое время был GCC. Но в последнее время в этой области ситуация изменилась. Возникли новые продукты, такие как LLM/Clang, Oracle Compiler Suite и возрожденный из забвения РСС. Смогут ли они составить конкуренцию безраздельно правящему набору компиляторов от проекта GNU?
Подготовка.
Во-первых, компиляторам будет скормлена библиотека Boost, которая агрессивно использует функции С++ (к примеру, шаблоны и некоторые инструкции препроцессора) и оказывается своего рода камнем преткновения для некоторых компиляторов.
Во-вторых, скорость компиляции бенчмарков. Стабильных версий Apache и ImageMagick.
В-третьих, качество генерации кода. Не только сравнивать размеры выходных исполняемых файлов, но и насколько быстро выполняются John the Ripper и bzip2.
Конфигурация компьютера: Р4 530 3 ГГц, 2 Гб RAM, HDD Seagate ST31000528AS.
GCC 4.6.3 и 4.8
Первая бета-версия GCC появилась в марте 1987 года. Тогда аббревиатура GCC расшифровывалась как GNU С Compiler. На тот момент компилятор поддерживал архитектуры VAX, SUN и m68k. В 1991-м была готова первая стабильная его версия, а в 1994-м, начиная с версии 4.4BSD, его сделали компилятором по умолчанию в большинстве BSD - систем. Одно время существовал форк GCC — EGCS, но в 1999-м их объединили вновь.
В настоящее время GCC заявлена поддержка следующих стандартов С:
- С89 с исправлениями от 1994 и 1996 годов, связанными, в частности, с return и локалями;
- поправки к С89 от 1995 года — некоторые называют это С94 или С95;
- поддержка стандарта С99, который включает в себя такие вещи, как тип bool, inline - функции и массивы переменной длины, заявлена не полностью.
Также в настоящее время в GCC есть несколько дополнений, несовместимых со стандартами С. К таковым относятся, например, арифметика с указателями на функции, пустые структуры и массивы нулевой длины.
Из стандартов С заявлена поддержка С++03. Поскольку стандарт С++98 сочли имеющим ошибки, а С++03 фактически эти ошибки исправляющим, предыдущий стандарт не поддерживается. Поддержка С++11, ранее носившего название С++0х, как и в случае со стандартом С99, заявлена не полностью. Такие функции, как, например, псевдонимы шаблонов, расширенное объявление «друзей» (ключевое слово friend позволяет одному классу напрямую обращаться к частным элементам другого), большинство возможностей, относящихся к параллелизму, не поддерживаются. Имеются также и расширения, несовместимые, как и в случае с обычным С, со стандартами. Расширения эти относятся, например, к шаблонам, Volatile - объектам и интерфейсам.
GCC версии 4.6.3.
Первым тестом будет Boost (версия из SVN). Сначала собирается средство сборки самого Boost — bjam. По умолчанию он устанавливается в /usr/local.
После этого редактируется файл в домашнем каталоге пользователя — user-config.jam.
Добавляется сторка:
$ echo "using gcc ;" > ~/user-config.jam
Теперь компилируется Boost:
$ time bjam
Время компиляции — 25 мин 52 с. Собрался без ошибок.
Для Apache, чтобы поддерживать несколько скомпилированных разными компиляторами версий с целью сравнить их размер, необходимо создать каталог, из которого будет вызываться configure, находящийся в каталоге с исходниками.
Время компиляции Apache 1 мин 52 с, размер же собственно исполняемого файла httpd составил 706 497 байт. Для компиляции ImageMagick проводятся те же самые операции, что и для Apache. Время его компиляции 12 мин 4 с.
Теперь перейдем к John the Ripper. Размер выходного файла John составил 227 524 байта, а бенчмарк MD5 — 7732 c/s. Сжатие файла размером 215 914 байт bzip2 заняло 7 мин 56 с.
Тест же OpenSSL (AES-CBC-256) показал, что при размере блока 8192 байта в секунду обрабатывается 35 438,59 тысячи байт. А для RSA с длиной ключа в 512 бит может быть подписано 2214,2 сообщения в секунду.
GCC версии 4.8
GCC 4.8 сейчас активно разрабатывается и имеет следующие новинки:
- Он реализован не на С, а на С++.
- Появился новый уровень оптимизации, -Оg. Этот уровень разработан для быстрой компиляции и отладки, но при нем производительность программы должна оставаться приемлемой.
- Добавлена опция для контроля оптимизации частичных избыточностей (PRE).
- Для архитектуры х86/х64 добавлены функции времени выполнения, которые позволяют определить тип и возможности процессора.
Компиляция потребует произвести некоторые операции:
$ sudo ln -s /usr/include/i386-linux-gnu/gnu/stubs-32.h /usr/include/gnu/
$ sudo ln -s /usr/lib/i386-linux-gnu/crt*.o /usr/lib/
$ cd gcc-trunk
$ ./configure && make
$ sudo make install
Несмотря на то что, казалось бы, совместимость не должна была сильно измениться по сравнению с 4.6.3, Boost не скомпилировался.
Для остальных тестов:
- Компиляция Apache — 1 мин 52с, размер исполняемого файла — 706 947 байт.
- Компиляция ImageMagick — 21 мин ЗЗс.
- Размер исполняемого файла John — 217880 байт, бенчмарк MD5 — 7927 c/s.
- Время сжатия bzip2 файла размером — 234163 байта — 7 мин 52 с.
- Бенчмарк OpenSSL AES-CBC-256 при размере блока 8192 — 39 209,64 тыс. байт/с, RSA512 — 2222 sign/c.
Oracle Compiler Suite
Набор компиляторов Compiler suite входит в состав Oracle Solaris Studio. Некоторые заявленные функции компилятора С:
- поддержка как С89, так и С99;
- диалект K&R и возможность смешения ANSI С и K&R;
- поддержка стандарта OpenMP С для распараллеливания;
- поддержка прекомпилированных заголовочных файлов для уменьшения времени компиляции;
- библиотека сборки мусора для управления кучей и отслеживания в run time утечек памяти.
С++ (компилятор что для С, что для С++ одинаков):
- стандарты С++98 и С++03;
- стандарт С++11 не поддерживается;
- можно выбирать из библиотек шаблонов стандартную библиотекy Sun либо STLPort;
- поддержка библиотеки Boost.
Раньше Compiler Suite стоила денег, но в настоящее время распространяется бесплатно. Для установки нужно скачать архив и распаковать в нужную директорию, а потом установить пути:
$ bunzp2 SolarisStudio12.3-linux-x86-bin.tar.bz2
$ sudo tar xf SolarisStudio12.3-linux-x86-bin.tar -C /opt
$ export PATH="/opt/SolarisStudio12.3-linux-x86-bin/solarisstudio12.3/bin:/opt/SolarisStudio12.3-linux-x86-bin/solarisstudio12.3/prod/bin:$PATH"
Затем добавь эти пути в /etc/environment.
Попытка сборки Boost с использованием данного компилятора провалилась.
Чтобы скомпилировать Apache и ImageMagick необходимо установить переменные окружения.
$ export СС=сс СХХ=сс
Перед компиляцией John'a необходимо подредактировать Makefile: вместо gcc поставить сс и убрать опции, начинающиеся с -W, поскольку оракловский компилятор их не понимает. Для компиляции же OpenSSL потребуется поставить пакеты happycoders-libsocket и happycoders-libsocket-dev, создать симлинки в /usr/lib:
$ ln -s /usr/lib/happycoders/lib* /usr/lib/
и выполнить в каталоге OpenSSL следующую команду:
$ ./Configure solaris-x86-cc
Результаты тестов:
- Компиляция Apache — 1 мин 39 с, размер исполняемого файла — 766 368 байт.
- Компиляция ImageMagick — 23 мин 56 с.
- Размер исполняемого файла John — 178 756 байт, бенчмарк MD5 — 6942 c/s.
- Время сжатия bzip2 файла размером —180 381 байт — 8 мин 25 с.
- Бенчмарк OpenSSL AES-CBC-256 при размере блока 8192 — 76371,29 тыс. байт/с, RSA512 — 849,7 sign/c.
PSS
Portable С Compiler — самый древний компилятор из приведенных здесь. Он был разработан AT&T в 1975-1977 годах, включен в UNIX V7 и вместо lex использовал yacc. Являлся компилятором по умолчанию до 4.4BSD, потом его заменил GCC. Какое-то время принадлежал Caldera. На него долго не обращали внимания, но, видимо, в связи с непомерным разрастанием GCC Эндерс Магнуссон в 2007 году решил его возродить.
Компилятор состоит из двух частей: pass1 проводит парсинг, проверку типов и строит дерево, a pass2 — генерирует код. Еще имеется деление на фронтенд и бэкенд. Фронтенд — сс — выполняется пользователем и передает файл бэкенду. Тем не менее это уже не оригинальный компилятор 70-х . В нем было переписано около 50% кода фронтенда и около 80% бэкенда. В настоящее время заявлена поддержка большинства функций С99. Также включен компилятор Fortran-77. Бэкенд С++ находится в зачаточном состоянии.
Из преимуществ стоит отметить размер. Если сравнивать с GCC — в сжатом виде занимает всего 730 Кб. Разработчики также заявляют, что скорость компиляции в 5-10 раз выше компилятора GNU при таком же качестве кода.
Получение и установка его достаточно тривиальна. Сначала ставим библиотеку pcc-libs:
$ tar xzvf рсс-libs-20120922.tgz
$ cd pcc-libs-20120922
$ ./configure && make
$ sudo make install
А затем сам компилятор:
$ tar xzvf pcc-current.tgz
$ cd pcc-20120922
$ ./configure && make
$ sudo make install
Перед компиляцией программ понадобилось установить переменные окружения СС и СХХ равными рсс, а для bzip2 и John the Ripper подправить Makefile.
Библиотеку Boost компилироваться не будет. ImageMagick и OpenSSL не собрались. Результаты теста:
- Компиляция Apache — 1 мин 4З с, размер исполняемого файла — 676 763 байта.
- Размер исполняемого файла John —178 829 байт, бенчмарк MD5 — 4325 c/s.
- Время сжатия bzip2 файла размером — 244 061 байт — 11 мин 45с.
LLVM и CLANG
Clang — компилятор языков С-семейства в байткод LLVM. Аббревиатура LLVM расшифровывается как Low-Level Virtual Machine. LLVM представляет собой, грубо говоря, виртуальную RISC-машину. На самом деле LLVM не является JIT- компилятором — хотя может (для некоторых языков) выступать в качестве такового. Он служит для облегчения портирования программ на другие платформы. Делается это с помощью промежуточного представления кода — IR. Над ним можно производить всевозможные трансформации, после этого он может быть преобразован в машинный код — либо динамически (JIT-компиляция), либо статически.
IR-код поддерживает следующие примитивы:
- iN — целые числа произвольной разрядности, где N означает разрядность (до восьми миллионов);
- числа с плавающей точкой — half, float, double и некоторые машинно-специфичные типы;
- x86mmx — поддержка расширений ММХ. Использование этого типа довольно ограниченно — например, нельзя создавать массивы с ним;
- void — пустое значение;
- metadata — метаданные, могут использоваться для оптимизации и отладки.
Помимо примитивов, IR-код поддерживает производные типы — такие, например, как указатели, массивы, структуры, функции и т.д.
Clang является компилятором, использующим LLVM. Поддерживает он такие языки С-семейства, как С, С++, ObjC и ObjС++. Из интересных функций компилятора стоит отметить:
- диагностические сообщения. В Clang, в отличии от других компиляторов, показывается кусок кода с точностью до строки и символа, где он видит ошибку или повод для неопределенности;
- частичная совместимость с GCC, что немаловажно для компиляции некоторых Open Source проектов;
- поддержка интеграции в IDE;
- BSD-лицензия — это делает возможным встраивать Clang, как и LLVM в целом, в коммерческие приложения.
Из стандартов С компилятор поддерживает то же самое, что и GCC, поэтому остановимся на поддержке С++.
- Поддерживаются все функции С++98/03, за исключением поведения в некоторых случаях ключевого слова export — такое поведение убрали из С++11.
- Из функций С++11 поддерживается большинство — даже и те, которых нет в GCC, не поддерживается разве что наследование конструкторов. Заявлена минимальная поддержка сборки мусора и некоторые возможности параллелизма.
Не лишним будет вспомнить плагин DragonEgg, который позволяет использовать GCC с LLVM, причем без перекомпиляции первого.
Текущая версия LLVM/Clang доступна через SVN. Процедура сборки и установки проста:
$ ./configure --optimized && make -j4
$ sudo make install
Стоит отметить, что процедура компиляции потребляет много памяти. Перед компиляцией тестов нужно установить переменные СС и СХХ в clang и clang++.
Clang откомпилпровал все тесты.
Результаты:
- Компиляция Boost — 51 мин 21 с.
- Компиляция Apache — 2 мин 2 с, размер исполняемого файла — 813 840 байт.
- Компиляция ImageMagick — 10 мин 10 с.
- Размер исполняемого файла John — 173 656 байт, бенчмарк MD5 — 7632 c/s.
- Время сжатия bzip2 файла размером —186 861 байт — 9 мин 31 с.
- Бенчмарк OpenSSL AES-CBC-256 при размере блока 8192 — 39 291,66 тыс. байт/с, RSA512 — 2202,4 sign/c.
Итоги тестов.
На последнем месте оказался РСС — он не смог скомпилировать ни ImageMagick, ни OpenSSL. При выполнении бенчмарков John и bzip2 он также оказался самым медленным из всех. Однако в случае компиляции Apache размер выходного файла httpd оказался самым маленьким, что может являться плюсом. Но другие результаты компиляции оказались не соизмеримыми. Сегодня РСС непригоден для промышленного использования.
Иная ситуация с остальными компиляторами. Oracle Compiler Suite не смог скомпилировать Boost, но то же самое не смог сделать и GCC 4.8. Что же до бенчмарков, то в тесте John GCC 4.8 лидирует, как и в случае с bzip2, где он незначительно опережает предыдущую свою версию. Однако в симметричном шифровании OpenSSL Compiler Suite лидирует, но в асеметричном шифровании отстает более чем вдвое, в то время как остальные держатся примерно на одном уровне. По итогам сравнения размеров выигрывает компилятор Oracle, который незначительно опережает Clang.
В учетом дальнейших перспектив победителем можно назвать Clang.
Во-первых, он компилирует Boost — с чем, кроме него, справилась только стабильная версия GCC.
Во-вторых, в тестах OpenSSL он лидирует без явных перекосов в сторону симметричного шифрования.
В-третьих — сама идея оптимизации с использованием промежуточного кода очень перспективна.
Комментарии
Немного не понял...
GCC версии 4.6.3. не участвовал ? У него и boost быстрее скомпилялся (в 2 раза) и httpd меньше оказался...