void makeExceptions(int times) |
_Winnie C++ Colorizer |
Начав писать такую ерунду, я уже не мог остановиться и решил заодно проверить производительность конструкций BOOST_FOREACH и Q_FOREACH, от просмотра реализации которых мне хочется рвать волосы на заднице.
Начал я с простого for:
void makeForeachFor(int times) |
_Winnie C++ Colorizer |
И BOOST_FOREACH:
void makeForeachBoost(int times) |
_Winnie C++ Colorizer |
Я специально помести его в innermost loop, чтобы сильнее проявили себя накладные расходы на создание и выход из цикла.
Сам массив я выбрал маленьким умышленно, чтобы он влез в любой кэш и не влиял на производительность.
Также есть свой foreach и в Qt. В отличие от BOOST_FOREACH, он не умеет работать с обычными массивами например и копирует контейнер перед использованием. Для Qt-контейнеров это не страшно, так как они все copy-on-write, но для обычных это просто недопустимо. Поэтому я также протестировал эти две реализации foreach на QVector.
void makeForeachBoostQt(int times) |
_Winnie C++ Colorizer |
Исходный код файла
Собирал я его под Windows при помощи MinGW и компилятора от 2005 студии:
gcc version 3.4.5 (mingw-vista special r3)
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
и под Linux:
gcc version 4.3.2 [gcc-4_3-branch revision 141291] (SUSE Linux)
Результаты замеров (среднее время в миллисекундах). Использовался 64битный Linux и 32битная Windows XP, процессор - Intel Core2 6420:
Cборка | Exceptions | for | Boost | Boost(QVector) | Q_FOREACH |
linux-64-O0 | 3.590 | 0.0350 | 0.4330 | 0.4590 | 0.1360 |
linux-64-O2 | 3.600 | 0 | 0 | 0.0400 | 0.5700 |
win32-cl | 2.828 | 0.0312 | 0.6719 | 0.6656 | 0.5844 |
win32-cl-O2 | 2.812 | 0 | 0.0125 | 0.0141 | 0.0734 |
win32-mingw-O0 | 0.843 | 0.0532 | 0.5672 | 0.6656 | 0.1937 |
win32-mingw-O2 | 0.844 | 0.0109 | 0.0125 | 0.0266 | 0.0546 |
Да, всё как и ожидалось. 3микросекунды на исключение это конечно немало, но если обрабатывать ими действительно ошибочные ситуации, а не строить на них логику программы (файла нет? Исключение! Пользователь нажал "отмена"? Исключение!), то вобщем-то не так уж и много. Хотя goto быстрее, да.
С другой стороны оказалось что оптимизаторы довольно агрессивно оптимизируют реализации foreach. Конечно, их ни в коем случае нельзя использовать в innermost loop, а для более высокого уровня вложенности они действительно упростят код (и усложнять хождение по шагам в отладчике).
Конечно полученные цифры не являются какой либо истиной в какой либо истанции, это всего лишь сферический тест в вакууме. Однако я для себя выводы сделал - и то и то можно без опаски применять, когда пишется например GUI или другой не библиотечный и не критичный ко времени выполнения код (98% кода). Что и требовалось доказать.