Программирование на C и C++

Онлайн справочник программиста на C и C++

Сравнение производительности C/C++ компиляторов для *nix-систем

Аватар пользователя admin
пн, 12/10/2012 - 14:48 -- admin

Стандартом  для компиляции 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 меньше оказался...