Pull to refresh

Comments 17

«Использовать в качестве более легковесной замены dynamic_cast» — вот тут я не понял. Может быть, есть бенчмарки каста? А то на мой взгляд должно быть все с точностью до наоборот.
Стандартный dynamic_cast жутко медленный. Во многих реализациях он использует сравнение строк, чтобы найти нужный объект. Поэтому нет ничего удивительного в том, чтобы RTTI-библиотека предлагала собственный, более быстрый вариант.
А сдается мне, что в 99% случаев dynamic_cast должен банально пробежаться по адресам виртуальных таблиц потомков класса. И это явно не 1 сек, как представленные бенчмарки, а раз так в миллион быстрее. Поэтому и хочу конкретных цифр.
Вынужден вас разочаровать, но на некоторых платформах и компиляторах используется именно сравнение строк. Основная причина — необходимость корректной работы dynamic_cast между динамическими библиотеками.

Конкретные цифры легко гуглятся, например вот: tinodidriksen.com/2010/04/14/cpp-dynamic-cast-performance
Там же есть и ссылка на исходник тестовой программы.

У Visual С++ цифры особо красноречивы. У GCC и Clang все гораздо лучше, но тоже имеются случаи, когда производительность падает примерно в 7-8 раз относительно вызова виртуального метода.

Если не верите, что используется именно сравнение строк, посмотрите например вот этот пост (в конце есть фрагмент кода из libc++): www.nullptr.me/2014/07/01/libcxxabi-__dynamic_cast-random-strings
Два момента.

1. Я пропустил, что конечные результаты даны для 10 млн вызовов, а не для одного. Что… слегка меняет всю картину :)

2, Спасибо за первую ссылку. Там данные в неопределенных тиках, я прогнал тот же тест для моего дохлого Селерона, тоже для 10 млн. вызовов. только для чистоты вычел время самого цикла и прочих вчпомогательных операций.
Результаты для VisualStudio 2013:
— reinterpret_cast: 16 ms
— dynamic_cast: 100-1000 ms, в зависимости от пары классов «откуда-куда».

Ксатати, тот пример по первой ссылке — прекрасный пример того, как не надо писать бенчмарки. ;)

Вывод: 10 млн. динамических кастов занимает 0.1-1.0 сек на дохлом процессоре. И что, это очень медленно?
Для многих задач это более, чем приемлемо. Тот же JavaScript исполняется еще медленнее, что, впрочем, не помешало портировать на него Unreal Engine.

Собственно я пытался донести мысль, что dynamic_cast — это относительно затратная операция, и у авторов приведенных в статье библиотек есть основания, чтобы реализовывать свой велосипед. И что этот велосипед в некоторых случаях будет работать быстрее, чем стандартная реализация.

А вот переходить на стороннюю реализацию имеет смысл только когда dynamic_cast уверенно сидит в топах профилировщика по затратам процессорного времени. Но в таком случае вообще надо хорошо задуматься — возможно dynamic_cast используется там, где можно было бы использовать виртуальные методы.
Абсолютно согласен. Если dynamic_cast стновится узким местом, то явно «что-то надо в консерватории подправить».
Есть benchmark на сайте библиотеки RTTR — www.axelmenzel.de/articles/rtti
Сама библиотека показала здесь не лучшие результаты в производительности, но и их достаточно, чтоб обогнать dynamic_cast.
Хотя, может, у автора специально проводились какие-то оптимизации под это.
А вообще да, dynamic_cast это явно не важнейшая задача для reflection, добавил в список больше для примера.
Интересная тема, хотя статья слишком краткая — чтобы понять, нужно открывать каждую библиотеку и разбираться.
И еще мысль — рефлексия это достаточно важная фича, эмулирующая отсутствующие возможности языка программирования… хорошо бы что-то наиболее удачное появилось в Бусте. Вот здесь ничего нет, но если погуглить, находятся какие-то неофициальные реализации:
boost-extension.redshoelace.com
bytemaster.bitshares.org/boost_reflect/index.html
Понимаю, что краткая. Эта статья — пересечение огромного личного интереса с невероятно скудной информацией на эту тему.
Собирал в основном для себя, но потом решил поделиться, хоть немного систематизировав.

Есть еще boost.mirror и boost.reflex.
boost.mirror выглядит просто гигантским монстром, разбит на несколько под-мета-библиотек и т.д. (хотя, может, и ошибаюсь).
boost.reflex — маловато информации, версия 0.1, не совсем понятно что за продукт и какая его судьба хотя бы в ближайшем будущем.
Я вообще думаю, что самую эффективную скорость по рефлексии можно получить с помощью кодогенерации.
Но я рекомендую почитать еще вот эту статью
woboq.com/blog/reflection-in-cpp-and-qt-moc.html
Авторы задумались о том, какие возможности стоит добавить в компилятор C++, чтобы генератор moc был не нужен.

Очень интересный черновик по рефлексии в С++
Жаль не упомянули то, что в Qt, за счет мета-объектного компилятора есть встроенные reflections (у всех QObject-классов).
Спасибо за добавление. Не упомянул, т.к. reflection в QT не основная задача и тянет с собой много чего другого.
Опять же, решения с дополнительным toolchain не рассматривались.
Кстати, автор библиотеки uMOF как раз таки, похоже, и вдохновлялся QT.
Его решение тоже хранит мета-информацию в статической памяти, но задается она вручную.
https://woboq.com/blog/verdigris-qt-without-moc.html вот кстати отдельная либа, которая копирует реализацию рефлексии из qt без moc-а.
Все выглядит как костыли (как и любые попытки реализовать библиотеками то, что должно быть в самом языке), ждем когда в C++17 все же добавят compile-time reflection на уровне языка.
Конечно, не спорю. Но число 17 слегка угнетает, особенно учитывая будущие задержки в реализации поддержки этого всего компиляторами.
А хочется уже здесь и сейчас, уж слишком много интересных плюшек это дает.
Ну основные компиляторы поддерживали C++14 в году этак 2013-ом…

P.S. кроме майкрософтовского…
Sign up to leave a comment.

Articles

Change theme settings