Pregunta

Hay un rendimiento en tiempo de ejecución de la pena cuando el uso de interfaces (clases base abstractas) en C++?

¿Fue útil?

Solución

Respuesta Corta:No.

Respuesta Larga:No es la clase base o el número de antepasados de una clase en la jerarquía que afecta a la velocidad.La única cosa que es el costo de una llamada de método.

No virtual llamada al método tiene un costo (pero puede estar en línea)
Un método virtual llamada tiene un costo ligeramente mayor a medida que usted necesita para buscar el método para llamar antes de llamar (pero esto es una simple tabla de buscar no una búsqueda).Dado que todos los métodos en una interfaz virtual son, por definición, no es este costo.

A menos que usted está escribiendo algunos hiper sensibles a la velocidad de la aplicación, esto no debería ser un problema.La mayor claridad que usted va a recibir a partir del uso de una interfaz generalmente hace que percibe la disminución de la velocidad.

Otros consejos

Funciones de llamada usando virtual de envío no están alineadas

Hay una especie de castigo para las funciones virtuales que es fácil olvidarse de:virtual de llamadas no están insertados en un (común) situación en la que el tipo de objeto no es saber el tiempo de compilación.Si su función es pequeño y adecuado para alineaciones, esta multa puede ser muy significativa, ya que no sólo agrega una sobrecarga de la llamada, pero el compilador también es limitada en cómo se puede optimizar la función de llamada (tiene que asumir la función virtual puede haber cambiado algunos registros o posiciones de memoria, puede propagar valores constantes entre el llamante y el llamado).

Virtual coste de la llamada depende de la plataforma

Como para la sobrecarga de la llamada pena en comparación con una función normal de la llamada, la respuesta depende de su plataforma de destino.Si su objetivo es una PC con x86/x64 CPU, la pena para llamar a una función virtual es muy pequeño, como moderno x86/x64 CPU puede realizar rama de predicción indirecta llamadas.Sin embargo, si usted está apuntando a un PowerPC, o alguna otra plataforma RISC, la llamada virtual de la pena puede ser muy significativo, porque indirectos llamadas nunca predijo en algunas plataformas (Cf. PC/Xbox 360 Cruz de la Plataforma de Desarrollo de las Mejores Prácticas).

Hay una pequeña penalización por cada llamada de función virtual en comparación con una llamada regular.Es raro observar una diferencia, a menos que usted está haciendo cientos de miles de llamadas por segundo, y el precio es a menudo vale la pena pagar por añadido el código de la claridad de todos modos.

Cuando se llama a una función virtual (es decir a través de una interfaz) el programa tiene que hacer una mirada de la función en una tabla para ver que la función de llamada para ese objeto.Esto da una pequeña penalización en comparación con una llamada directa a la función.

Además, cuando se utiliza una función virtual el compilador no puede en línea de la llamada a la función.Por lo tanto, podría haber una sanción para el uso de una función virtual para algunas pequeñas funciones.Este es generalmente el mayor rendimiento "hit" es probable que usted vea.Esto realmente sólo una cuestión de si la función es pequeño y llamado muchas veces, dicen desde dentro de un bucle.

Otra alternativa que es aplicable en algunos casos es tiempo de compilación polimorfismo con plantillas.Es útil, por ejemplo, cuando usted quiere para hacer una implementación elección en el comienzo del programa, y a continuación, utilice para la duración de la ejecución.Un ejemplo con el polimorfismo en tiempo de ejecución

class AbstractAlgo
{
    virtual int func();
};

class Algo1 : public AbstractAlgo
{
    virtual int func();
};

class Algo2 : public AbstractAlgo
{
    virtual int func();
};

void compute(AbstractAlgo* algo)
{
      // Use algo many times, paying virtual function cost each time

}   

int main()
{
    int which;
     AbstractAlgo* algo;

    // read which from config file
    if (which == 1)
       algo = new Algo1();
    else
       algo = new Algo2();
    compute(algo);
}

El mismo uso de polimorfismo en tiempo de compilación

class Algo1
{
    int func();
};

class Algo2
{
    int func();
};


template<class ALGO>  void compute()
{
    ALGO algo;
      // Use algo many times.  No virtual function cost, and func() may be inlined.
}   

int main()
{
    int which;
    // read which from config file
    if (which == 1)
       compute<Algo1>();
    else
       compute<Algo2>();
}

No creo que la comparación es entre lo virtual llamada de función y de una recta llamada a la función.Si usted está pensando en usar una clase base abstracta (interfaz), entonces usted tiene una situación en la que desea realizar una de las varias acciones en función de la dinámica del tipo de un objeto.Usted tiene que elegir de alguna manera.Una opción es el uso de funciones virtuales.Otro es un cambio en el tipo de objeto, ya sea a través de RTTI (potencialmente costoso), o la adición de un tipo() método de la clase base (que podría aumentar el uso de memoria de cada objeto).Por lo que el coste de la llamada de función virtual debe ser comparado con el costo de la alternativa, no para el coste de no hacer nada.

La mayoría de la gente nota el tiempo de ejecución de la pena, y con razón.

Sin embargo, en mi experiencia trabajando en grandes proyectos, los beneficios de la clara de interfaces y adecuada encapsulación rápidamente compensar la ganancia en velocidad.Código Modular puede ser intercambiado por una mejora de la aplicación, por lo que el resultado neto es un aumento considerable.

Su kilometraje puede variar, y es claramente dependen de la aplicación que estamos desarrollando.

Una cosa que debe señalarse es que la función virtual coste de la llamada puede variar de una plataforma a otra.En las consolas pueden ser más evidentes, como suele vtable llamada significa un error de caché y puede tornillo de la rama de predicción.

Tenga en cuenta que la herencia múltiple aumenta la instancia del objeto con múltiples vtable punteros.Con G++ en x86, si la clase tiene un método virtual y no de la clase base, se tiene un puntero a la vtable.Si usted tiene una base de clase con métodos virtuales, usted todavía tiene un puntero a la vtable.Si usted tiene dos clases de base con métodos virtuales, que han dos vtable punteros en cada instancia.

Por lo tanto, con la herencia múltiple (que es lo que la implementación de interfaces en C++ es), usted paga clases de base de veces el tamaño del puntero en la instancia de objeto tamaño.El aumento de la huella de memoria puede tener indirectos consecuencias en el rendimiento.

El uso de clases base abstractas en C++ generalmente exige el uso de una tabla de funciones virtuales, todas sus llamadas de interfaz va a ser buscado a través de la tabla.El costo es mínimo en comparación con una prima llamada a función, así que asegúrese de que usted necesita para ir más rápido que antes de preocuparse por ella.

La única diferencia que yo sé es que, desde que no estás usando una clase concreta, inline es (mucho?) más difícil de hacer.

La única cosa que puedo pensar es que los métodos virtuales son un poco más lentos para llamar a que los no-métodos virtuales, debido a que la llamada tiene que ir a través de la tabla de método virtual.

Sin embargo, esta es una mala razón para el tornillo de seguridad de su diseño.Si usted necesita más rendimiento, utilice un servidor más rápido.

Como para cualquier clase que contiene una función virtual, una vtable se utiliza.Obviamente, la invocación de un método a través de un despacho de mecanismo como una vtable es más lento que una llamada directa, pero en la mayoría de los casos se puede vivir con eso.

Sí, pero nada digno de mención a mi conocimiento.El impacto en el rendimiento es causa de "direccionamiento indirecto" que usted tiene en cada llamada al método.

Sin embargo, lo que realmente depende del compilador que se está usando, ya que algunos compiladores no son capaces de poner en línea el método de las llamadas dentro de las clases que heredan de la clase base abstracta.

Si usted quiere estar seguro de que usted debe ejecutar sus propias pruebas.

Sí, es una pena.Algo que puede mejorar el rendimiento de su plataforma es el uso de una clase no abstracta con ninguna de las funciones virtuales.A continuación, utilice un miembro de la función de puntero a la función no virtual.

Sé que es un punto de vista poco común, pero ni hablar de este tema me hace sospechar que usted está poniendo demasiado el pensamiento en la estructura de la clase.He visto muchos sistemas que había demasiados "niveles de abstracción", y que solo lo hacía muy vulnerable a problemas graves de rendimiento, no por el costo de las llamadas de método, pero debido a la tendencia a hacer llamadas innecesarias.Si esto ocurre a través de múltiples niveles, es un asesino. echa un vistazo

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top