По идее, это значит, что, даже для каких-нибудь типов предметной области, которые можно выразить через базовые типы языка предлагается выделять класс, чтобы ограничить его функционал и не дать написать ерунду. Логично? Логично.
С другой стороны, возникает вопрос: а какой может быть оверхед по производительности на выполнение такой рекомендации? По идее, хотелось бы, чтобы компилятор убирал все типы, которые тупо оборачивают базовые типы данных и оставлял только голые операции с базовыми типами.
Я решил проверить производительность в таком случае, как полагается, с просмотром результатов дизассемблирования и получил довольно интересные результаты.
Для начала расскажу о тесте. Он довольно сильно синтетический: это вычисление пути, пройденного телом при условии действия на него постоянно меняющейся силы.
Код намеренно оформлен не очень: структуры везде возвращаются по значению, чтобы их потребовалось копировать. Таймер, чтобы не тащить громоздкий boost, забрал со своего другого проекта, кому надо - скину.
С вычислительной точки зрения (и физики) код вообще ерунда: метод аппроксимации выбран неудачно, да ещё и от ускорения довольно легко берётся интеграл. В результате получается огромная погрешность. Впрочем, при выборе более сложного и точного метода, красивая абстракция, выбранная в данном случае разрушается окончательно и проще уж действительно всюду поставить double или сделать typedef и забить на рекомендацию окончательно. Иными словами, тест хорош только для замера попугаев и оптимизации компилятора.
Код намеренно оформлен не очень: структуры везде возвращаются по значению, чтобы их потребовалось копировать. Таймер, чтобы не тащить громоздкий boost, забрал со своего другого проекта, кому надо - скину.
С вычислительной точки зрения (и физики) код вообще ерунда: метод аппроксимации выбран неудачно, да ещё и от ускорения довольно легко берётся интеграл. В результате получается огромная погрешность. Впрочем, при выборе более сложного и точного метода, красивая абстракция, выбранная в данном случае разрушается окончательно и проще уж действительно всюду поставить double или сделать typedef и забить на рекомендацию окончательно. Иными словами, тест хорош только для замера попугаев и оптимизации компилятора.
А теперь самое интересное: ВСЕ рассмотренные компиляторы, судя по дизасму, убрали лишнее копирование на стеке и с этим действительно всё хорошо (и было хорошо ещё со времён выхода MSVC 2010). Но производительность всё равно вышла очень и очень разной.
На Windows 7 код тестировался на Core i5 2.67 GHz c 4 Гб RAM, на компиляторах с включенным -O2. Лучше всего себя показала новая студия, хуже всего - почему-то MinGW.
На Windows 7 код тестировался на Core i5 2.67 GHz c 4 Гб RAM, на компиляторах с включенным -O2. Лучше всего себя показала новая студия, хуже всего - почему-то MinGW.
Компилятор | Среднее время, мс |
MinGW 6.2.0 | 44145 |
MSVC 2010 | 31306 |
MSVC 2015 | 26172 |
MSVC 2017 RC | 25382 |
Честно говоря, не понимаю, либо дефолтные ключи оптимизации у MinGW так плохи (т. е. я не сумел его правильно приготовить), либо GCC по производительности сильно отстает от более современных компиляторов.
Сходная ситуация получилась и при проверке на слабой машине с Ubuntu 16.04.2 LTS с Atom D525 1.8 MHz и 2 Гб RAM: здесь выиграл clang.
Компилятор | Среднее время, мс |
clang version 3.8.0-2ubuntu4 | 221441 |
gcc 5.4.0 | 230885 |
gcc 7.0.0 20170113 (experimental) | 230344 |
Выводы получаются неплохими, но немного странными:
- Такими бенчмарками современные компиляторы не проймешь и это хорошо.
- WTF с дефолтным /O2 у GCC? Он не особо улучшается между версиями и умудряется проигрывать.
- Clang оптимизирует чертовски хорошо.
- Компилятор студии значительно улучшился за 5-7 лет и проблем с ним в быстродействии ожидать не стоит.
Комментариев нет:
Отправить комментарий