¿Penalización de rendimiento por trabajar con interfaces en C++?


¿Hay una penalización de rendimiento en tiempo de ejecución cuando se utilizan interfaces (clases base abstractas) en C++?

Author: Suma, 2008-09-22

16 answers

Respuesta corta: No.

Respuesta Larga: No es la clase base o el número de ancestros que una clase tiene en su jerarquía lo que afecta su velocidad. Lo único es el costo de una llamada de método.

Una llamada a un método no virtual tiene un costo (pero puede ser inlineado)
Una llamada a un método virtual tiene un costo ligeramente mayor, ya que necesita buscar el método a llamar antes de llamarlo (pero esta es una tabla simple buscar no una búsqueda). Puesto que todos los métodos en una interfaz son virtuales por definición hay este costo.

A menos que esté escribiendo alguna aplicación sensible a la hiper velocidad, esto no debería ser un problema. La claridad extra que recibirá de usar una interfaz generalmente compensa cualquier disminución de velocidad percibida.

 42
Author: Loki Astari,
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
2008-10-25 20:20:58

Las funciones llamadas usando virtual dispatch no están inlineadas

Hay un tipo de penalización para las funciones virtuales que es fácil de olvidar: las llamadas virtuales no están en línea en una situación (común) donde el tipo del objeto no se conoce en tiempo de compilación. Si su función es pequeña y adecuada para la inserción, esta penalización puede ser muy significativa, ya que no solo está agregando una sobrecarga de llamada, sino que el compilador también está limitado en cómo puede optimizar la función de llamada (tiene que asumir la la función virtual puede haber cambiado algunos registros o ubicaciones de memoria, no puede propagar valores constantes entre el llamante y el destinatario).

El costo de la llamada virtual depende de la plataforma

En cuanto a la penalización por sobrecarga de llamadas en comparación con una llamada a una función normal, la respuesta depende de su plataforma de destino. Si su objetivo es un PC con CPU x86/x64, la penalización por llamar a una función virtual es muy pequeña, ya que la CPU x86/x64 moderna puede realizar predicciones de ramificación en llamadas indirectas. Obstante, si se dirige a un PowerPC o a alguna otra plataforma RISC, la penalización por llamada virtual puede ser bastante significativa, porque las llamadas indirectas nunca se predicen en algunas plataformas (Cf. Mejores Prácticas de Desarrollo Multiplataforma para PC/Xbox 360).

 21
Author: Suma,
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
2012-06-30 23:14:09

Hay una pequeña penalización por llamada a función virtual en comparación con una llamada regular. Es poco probable que observe una diferencia a menos que esté haciendo cientos de miles de llamadas por segundo, y el precio a menudo vale la pena pagar por la claridad del código adicional de todos modos.

 9
Author: moonshadow,
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
2008-09-22 08:43:55

Cuando se llama a una función virtual (por ejemplo, a través de una interfaz) el programa tiene que hacer una búsqueda de la función en una tabla para ver qué función llamar 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 insertar la llamada a la función. Por lo tanto, podría haber una penalización por usar una función virtual para algunas funciones pequeñas. Este es generalmente el mayor "éxito" de rendimiento que es probable que ver. Esto realmente solo es un problema si la función es pequeña y se llama muchas veces, digamos desde dentro de un bucle.

 5
Author: David Dibben,
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
2008-09-22 08:47:00

Otra alternativa que es aplicable en algunos casos es compile-time polimorfismo con plantillas. Es útil, por ejemplo, cuando se desea hacer una elección de implementación al principio del programa, y luego utilícelo durante la duración de la ejecución. Un ejemplo con 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);
}

Lo mismo usando el polimorfismo de 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>();
}
 4
Author: KeithB,
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
2008-09-22 13:02:02

No creo que la comparación de costos sea entre una llamada a función virtual y una llamada a función directa. Si está pensando en usar una clase base abstracta (interfaz), entonces tiene una situación en la que desea realizar una de varias acciones basadas en el tipo dinámico de un objeto. Tienes que tomar esa decisión de alguna manera. Una opción es utilizar funciones virtuales. Otro es un interruptor en el tipo del objeto, ya sea a través de RTTI (potencialmente caro), o la adición de un método type () a la clase base (potencialmente aumentando el uso de memoria de cada objeto). Por lo tanto, el costo de la llamada a la función virtual debe compararse con el costo de la alternativa, no con el costo de no hacer nada.

 3
Author: KeithB,
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
2008-09-22 12:42:55

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

Sin embargo, en mi experiencia trabajando en grandes proyectos, los beneficios de interfaces claras y una encapsulación adecuada compensan rápidamente la ganancia en velocidad. El código modular se puede intercambiar por una implementación mejorada, por lo que el resultado neto es una gran ganancia.

Su kilometraje puede variar, y claramente depende de la aplicación que esté desarrollando.

 3
Author: rlerallut,
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
2008-09-22 17:00:01

Una cosa que debe tenerse en cuenta es que el costo de la llamada a la función virtual puede variar de una plataforma a otra. En las consolas pueden ser más notables, ya que generalmente la llamada vtable significa una falta de caché y puede atornillar la predicción de ramas.

 2
Author: yrp,
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
2008-09-22 09:38:16

Tenga en cuenta que la herencia múltiple infla la instancia del objeto con varios punteros vtable. Con G++ en x86, si su clase tiene un método virtual y ninguna clase base, tiene un puntero a vtable. Si tiene una clase base con métodos virtuales, todavía tiene un puntero a vtable. Si tiene dos clases base con métodos virtuales, tiene dos punteros vtable en cada instancia.

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

 2
Author: hsivonen,
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
2008-10-12 11:42:30

El uso de clases base abstractas en C++ generalmente exige el uso de una tabla de funciones virtuales, todas las llamadas a la interfaz se buscarán a través de esa tabla. El costo es pequeño en comparación con una llamada de función sin procesar, así que asegúrese de que necesita ir más rápido que eso antes de preocuparse por ello.

 0
Author: Simon Steele,
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
2008-09-22 08:45:15

La única diferencia principal que conozco es que, ya que no estás usando una clase concreta, la inserción es (mucho?) más difícil de hacer.

 0
Author: Chris Jester-Young,
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
2008-09-22 08:45:23

Lo único que se me ocurre es que los métodos virtuales son un poco más lentos de llamar que los métodos no virtuales, porque la llamada tiene que pasar por la tabla de métodos virtuales .

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

 0
Author: jan.vdbergh,
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
2008-09-22 08:45:59

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

 0
Author: radu_c,
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
2008-09-22 08:48:48

Sí, pero nada notable que yo sepa. El golpe de rendimiento se debe a la' indirección ' que tiene en cada llamada de método.

Sin embargo, realmente depende del compilador que esté utilizando, ya que algunos compiladores no pueden insertar las llamadas al método dentro de las clases heredadas de la clase base abstracta.

Si desea asegurarse de que debe ejecutar sus propias pruebas.

 0
Author: mortenbpost,
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
2008-09-22 08:53:01

Sí, hay una penalización. Algo que puede mejorar el rendimiento en su plataforma es usar una clase no abstracta sin funciones virtuales. A continuación, utilice un puntero de función miembro a su función no virtual.

 0
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
2008-09-22 14:24:46

Sé que es un punto de vista poco común, pero incluso mencionar este tema me hace sospechar que estás pensando demasiado en la estructura de clases. He visto muchos sistemas que tenían demasiados "niveles de abstracción", y eso por sí solo los hacía propensos a graves problemas de rendimiento, no debido al costo de las llamadas a métodos, sino debido a la tendencia a hacer llamadas innecesarias. Si esto sucede en varios niveles, es un asesino. echa un vistazo

 0
Author: Mike Dunlavey,
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
2008-11-04 22:34:08