Подтвердить что ты не робот

Производительность dynamic_cast?

Перед тем, как прочитать вопрос:
Этот вопрос не о том, насколько полезно использовать dynamic_cast. Это всего лишь его производительность.

Недавно я разработал проект, в котором dynamic_cast используется много.
Обсуждая это с коллегами, почти все говорят, что dynamic_cast не следует использовать из-за его плохой производительности (это сотрудники, которые имеют разные фоны и в некоторых случаях не знают друг друга. огромная компания)

Я решил проверить производительность этого метода вместо того, чтобы просто поверить им.

Использовался следующий код:

ptime firstValue( microsec_clock::local_time() );

ChildObject* castedObject = dynamic_cast<ChildObject*>(parentObject);

ptime secondValue( microsec_clock::local_time() );
time_duration diff = secondValue - firstValue;
std::cout << "Cast1 lasts:\t" << diff.fractional_seconds() << " microsec" << std::endl;

В приведенном выше коде используются методы из boost::date_time в Linux для получения полезных значений.
Я сделал 3 dynamic_cast за одно исполнение, код для их измерения одинаковый.

Результаты 1 исполнения были следующими:
  Cast1 длится: 74 микрос

  Cast2 длится: 2 микроскопа
  Cast3 длится: 1 микрос

Первый бросок всегда составлял 74-111 микросекунд, следующие приведения в одном и том же исполнении занимали 1-3 микросекунды.

Итак, наконец, мои вопросы:
Действительно ли dynamic_cast плохо работает?
По результатам теста его нет. Правильно ли мой тестовый код?
Почему многие разработчики считают, что это медленный, если это не так?

4b9b3361

Ответ 1

Во-первых, вам нужно измерить производительность намного больше, чем несколько итераций, так как в ваших результатах будет доминировать разрешение таймера. Попробуйте, например. 1 миллион +, чтобы создать представительную картину. Кроме того, этот результат бессмыслен, если вы не сравниваете его с чем-либо, т.е. Выполняете эквивалент, но без динамического каста.

Во-вторых, вам нужно убедиться, что компилятор не дает вам ложных результатов, оптимизируя многократные динамические нажатия на один и тот же указатель (поэтому используйте цикл, но каждый раз используйте другой указатель ввода).

Динамическое кастинг будет медленнее, потому что ему нужно получить доступ к таблице RTTI (информация о типе времени выполнения) для объекта и проверить, что акция действительна. Затем, чтобы правильно использовать его, вам нужно будет добавить код обработки ошибок, который проверяет, является ли возвращаемый указатель NULL. Все это занимает циклы.

Я знаю, что вы не хотели говорить об этом, но "дизайн, в котором dynamic_cast используется много", вероятно, является индикатором того, что вы делаете что-то неправильно...

Ответ 2

Производительность бессмысленна, не сравнивая эквивалентную функциональность. Большинство людей говорят, что dynamic_cast работает медленно, не сравниваясь с эквивалентным поведением. Вызовите их на этом. Другими словами:

Если "works" не является обязательным требованием, я могу написать код, который не работает быстрее вашего.

Существуют различные способы реализации dynamic_cast, а некоторые - быстрее других. Например, Stroustrup опубликовал статью об использовании простых для улучшения dynamic_cast. К сожалению, необычно контролировать, как ваш компилятор реализует актерский состав, но если производительность действительно важна для вас, то у вас есть контроль над тем, какой компилятор вы используете.

Однако не использовать dynamic_cast всегда будет быстрее, чем использовать его, но если вам действительно не нужна динамическая_каска, то не используйте его! Если вам нужен динамический поиск, тогда будут некоторые накладные расходы, и вы можете сравнить различные стратегии.

Ответ 3

Вот несколько тестов:
http://tinodidriksen.com/2010/04/14/cpp-dynamic-cast-performance/
http://www.nerdblog.com/2006/12/how-slow-is-dynamiccast.html

По их словам, dynamic_cast в 5-30 раз медленнее, чем reinterpret_cast, и лучшая альтернатива выполняет почти то же самое, что и reinterpret_cast.

Я приведу вывод из первой статьи:

  • dynamic_cast работает медленно, но отличает его от базового типа; что конкретный литье оптимизировано
  • уровень наследования оказывает большое влияние на dynamic_cast
  • переменная-член + reinterpret_cast - это самый быстрый и надежный способ определить тип; тем не менее, у этого есть намного более высокие накладные расходы на техническое обслуживание
    при кодировании

Абсолютные номера имеют порядок 100 нс для одного актера. Значения типа 74 мс не кажутся близкими к реальности.

Ответ 4

Извините, что произнесите это, но ваш тест практически бесполезен для определения того, является ли приведение медленным или нет. Разрешение микросекунды далеко не достаточно хорошо. Мы говорим об операции, которая даже в худшем случае не должна занимать больше, скажем, 100 тактов времени или менее 50 наносекунд на типичном ПК.

Нет никаких сомнений в том, что динамический кастинг будет медленнее, чем статический бросок или реинтерпрет, потому что на уровне сборки последние два будут соответствовать заданию (действительно быстро, порядка 1 такт), а динамический кастинг требует, чтобы код пошел и проверил объект, чтобы определить его реальный тип.

Я не могу сказать, насколько он медленный, это, вероятно, будет отличаться от компилятора к компилятору, мне нужно будет увидеть код сборки, сгенерированный для этой строки кода. Но, как я уже сказал, 50 наносекунд за звонок - это верхний предел того, что ожидается разумным.