2010-10-29 2 views
35

Прежде чем задать вопрос:
Этот вопрос не о том, насколько полезно использовать 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 действительно плохо работает?
Согласно результатам тестирования, его нет. Правильно ли установлен тестовый код?
Почему так много разработчиков думают, что это медленно, если это не так?

+13

Я что-то упустил? Я не вижу никакого кода для cast2 или cast3. – Flexo

+4

Кто может сказать, что плохого? Ваша программа работает достаточно хорошо над всеми? Если да, то производительность неплохая. Общее время в динамике отличает большой процент от времени выполнения? Если нет, то сначала волнуйтесь о других вещах. В более общем плане, 74 микросекунда для некоторых приложений очень медленны - на моем последнем задании я получил и проанализировал всю запись обновления на бирже, обновил базу данных и сообщил об этом клиентским приложениям в половине случаев. Если вас это интересует, сравните его с другими способами, чтобы получить такое же поведение. –

+3

Наличие большого количества динамических кадров в коде является верным индикатором проблем с дизайном. –

ответ

42

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

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

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

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

+5

+1, но 10K итераций, скорее всего, недостаточно. Что-то вроде 100 миллионов лучше. – sharptooth

+0

@sharptooth: Справедливая точка! –

+0

@Oliver Charlesworth «... чтобы использовать его правильно, вам нужно будет добавить код обработки ошибок, который проверяет, является ли возвращаемый указатель NULL». Аналогичная версия проверки, которую вы упоминаете, присутствует во всех методах поиска runtime-тип объекта, поэтому это не аргумент. – spectre

24

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

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

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

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

+4

+1. Да, кстати, каждый живой человек умирает. Это не значит, что плохая идея - быть живым. – sharptooth

4

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

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

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

+0

dynamic_cast должен получить доступ к RTTI, это займет циклы. – doron

16

Вот несколько тестов:
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 мс не кажутся близкими к реальности.

+1

Значение, которое он получал, составляло 74 мкс (микросекунды), а не 74 мс (миллисекунды). Тем не менее, это все еще не кажется реалистичным. – Ponkadoodle