Сколько штрафа я буду платить за вызов виртуальной функции, которая вызывает "Math.sin" вместо прямого вызова?
Виртуальный вызов реализуется путем разыменования указателя виртуальной таблицы, получения указателя функции из соответствующего смещения в виртуальной таблице и вызова функции через этот указатель.
Это немного дороже, чем статический вызов, но все еще считается очень дешевым для "нормального" использования Если вам нужно выжать каждую последнюю потерю производительности, рассмотрите возможность указания всех ваших типов во время компиляции, чтобы разрешить использование не виртуальных функций.
Сможет ли компилятор оптимизировать его и понять, что в случае, если я инициализирую MyMath с помощью PriciseMath, все, что мне нужно, это вызывать нормальные функции Sin и Cos?
Если компилятор может доказать (сам себе), что объект будет иметь определенный тип во время выполнения, он сможет генерировать статический вызов функции, даже если сама функция объявлена как виртуальная.
Однако компилятору не гарантируется , чтобы быть достаточно умным, чтобы действительно это сделать. Единственный способ гарантировать статический вызов - использовать не виртуальную функцию.
Могу ли я изменить свой дизайн, чтобы помочь компилятору понять и оптимизировать мой код?
- Устраните издержки виртуального вызова: если нет необходимости изменять реализацию во время выполнения, укажите типы во время компиляции и вообще прекратите использование виртуальных функций. Шаблоны могут быть незаменимы при этом общим способом.
- Устранение накладных расходов на статический вызов функции: указывайте тела функций в заголовках, что позволяет компилятору выполнять встроенные вызовы функций.
(Ответ RTS является хорошей иллюстрацией обоих этих методов.)
И, наконец, если производительность действительно важна для вас, не полагайтесь только на советы других людей (включая меня) - всегда выполняйте измерения самостоятельно!