Rendimiento del elenco dinámico?


Antes de leer la pregunta:
Esta pregunta no es acerca de lo útil que es usar dynamic_cast. Se trata de su rendimiento.

Recientemente he desarrollado un diseño donde dynamic_cast se usa mucho.
Al discutirlo con compañeros de trabajo casi todo el mundo dice que dynamic_cast no debe usarse debido a su mal desempeño (estos son compañeros de trabajo que tienen diferentes orígenes y en algunos casos no se conocen entre sí. Estoy trabajando en una gran empresa)

Decidí probar el rendimiento de este método en lugar de simplemente creerlos.

Se utilizó el siguiente código:

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;

El código anterior utiliza métodos de boost::date_time en Linux para obtener valores utilizables.
He hecho 3 dynamic_cast en una ejecución, el código para medirlos es el mismo.

Los resultados de 1 ejecución fueron los siguientes:
Cast1 dura: 74 microsec
Cast2 dura: 2 microsec
Duración del Cast3: 1 microsec

El primer molde siempre tomó 74-111 microsec, los siguientes moldes en la misma ejecución tomó 1-3 microsec.

Así que finalmente mis preguntas:
Es dynamic_cast realmente realizar mal?
Según los resultados de las pruebas, no es así. ¿Es correcto mi testcode?
¿Por qué tantos desarrolladores piensan que es lento si no lo es?

Author: fduff, 2010-10-29

4 answers

En primer lugar, debe medir el rendimiento en mucho más que unas pocas iteraciones, ya que sus resultados estarán dominados por la resolución del temporizador. Intente, por ejemplo, 1 millón+, con el fin de construir una imagen representativa. Además, este resultado no tiene sentido a menos que lo compares con algo, es decir, haciendo el equivalente pero sin el casting dinámico.

En segundo lugar, debe asegurarse de que el compilador no le esté dando resultados falsos optimizando múltiples lanzamientos dinámicos en el el mismo puntero (así que usa un bucle, pero usa un puntero de entrada diferente cada vez).

El casting dinámico será más lento, porque necesita acceder a la tabla RTTI (run-time type information) para el objeto, y comprobar que el cast es válido. Luego, para usarlo correctamente, necesitará agregar un código de manejo de errores que verifique si el puntero devuelto es NULL. Todo esto toma ciclos.

Sé que no querías hablar de esto, pero " un diseño donde dynamic_cast se usa mucho" es probablemente un indicador de que estás haciendo algo mal...

 45
Author: Oliver Charlesworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-29 10:40:28

El rendimiento no tiene sentido sin comparar la funcionalidad equivalente. La mayoría de la gente dice que dynamic_cast es lento sin compararlo con un comportamiento equivalente. Llámalos por esto. Dicho de otra manera:

Si 'funciona' no es un requisito, puedo escribir código que falla más rápido que el tuyo.

Hay varias formas de implementar dynamic_cast, y algunas son más rápidas que otras. Stroustrup publicó un artículo sobre el uso de primes para mejorar dynamic_cast , para ejemplo. Desafortunadamente, es inusual controlar cómo su compilador implementa el cast, pero si el rendimiento realmente le importa, entonces usted tiene control sobre qué compilador usa.

Sin embargo, no usar dynamic_cast siempre será más rápido que usarlo, pero si realmente no necesita dynamic_cast, ¡no lo use! Si necesita una búsqueda dinámica, entonces habrá algunos gastos generales, y luego puede comparar varias estrategias.

 24
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-29 10:39:40

Aquí hay un par de benchmarks:
http://tinodidriksen.com/2010/04/14/cpp-dynamic-cast-performance/
http://www.nerdblog.com/2006/12/how-slow-is-dynamiccast.html

Según ellos, dynamic_cast es 5-30 veces más lento que reinterpret_cast, y la mejor alternativa funciona casi igual que reinterpret_cast.

Citaré la conclusión del primer artículo:

  • dynamic_cast es lento para cualquier cosa menos para lanzar a la base tipo; que reparto particular se optimiza hacia fuera
  • el nivel de herencia tiene un gran impacto en dynamic_cast
  • variable miembro + reinterpret_cast es la forma más rápida y fiable de
    determine el tipo; sin embargo, eso tiene una sobrecarga de mantenimiento mucho mayor
    al codificar

Los números absolutos son del orden de 100 ns para un solo lanzamiento. Valores como 74 mseg no parecen cercanos a la realidad.

 16
Author: VladV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-28 06:48:38

Lamento decir esto, pero su prueba es prácticamente inútil para determinar si el lanzamiento es lento o no. La resolución de microsegundos no es lo suficientemente buena. Estamos hablando de una operación que, incluso en el peor de los casos, no debería tomar más de, digamos, 100 ticks de reloj, o menos de 50 nanosegundos en un PC típico.

No hay duda de que el molde dinámico será más lento que un molde estático o un molde reinterpretado, porque, en el nivel de ensamblaje, estos dos últimos equivaldrán a un asignación (muy rápido, orden de 1 reloj tick), y el lanzamiento dinámico requiere que el código vaya e inspeccione el objeto para determinar su tipo real.

No puedo decir por casualidad lo lento que es realmente, eso probablemente variaría de compilador en compilador, necesitaría ver el código ensamblador generado para esa línea de código. Pero, como dije, 50 nanosegundos por llamada es el límite superior de lo que se espera que sea razonable.

 4
Author: Eugene Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-10-29 10:23:30