Las funciones virtuales solo tienen una sobrecarga de rendimiento muy pequeña en comparación con las llamadas directas. En un nivel bajo, básicamente está buscando en una búsqueda de matriz para obtener un puntero de función, y luego una llamada a través de un puntero de función. Las CPU modernas incluso pueden predecir llamadas a funciones indirectas razonablemente bien en sus predictores de bifurcación, por lo que generalmente no dañarán demasiado las tuberías de CPU modernas. En el nivel de ensamblaje, una llamada de función virtual se traduce a algo como lo siguiente, donde I
es un valor inmediato arbitrario.
MOV EAX, [EBP + I] ; Move pointer to class instance into register
MOV EBX, [EAX] ; Move vtbl pointer into register.
CALL [EBX + I] ; Call function
Vs. lo siguiente para una llamada de función directa:
CALL I ; Call function directly
La sobrecarga real es que las funciones virtuales no se pueden insertar, en su mayor parte. (Pueden estar en lenguajes JIT si la VM se da cuenta de que siempre van a la misma dirección de todos modos.) Además de la aceleración que obtiene al alinearse, la alineación permite muchas otras optimizaciones, como el plegado constante, porque la persona que llama puede saber cómo el destinatario funciona internamente Para las funciones que son lo suficientemente grandes como para no ser inline de todos modos, el golpe de rendimiento probablemente será insignificante. Para funciones muy pequeñas que pueden estar incluidas, es cuando debe tener cuidado con las funciones virtuales.
Editar: Otra cosa a tener en cuenta es que todos los programas requieren control de flujo, y esto nunca es gratis. ¿Qué reemplazaría tu función virtual? ¿Una declaración de cambio? Una serie de declaraciones if? Estas todavía son ramas que pueden ser impredecibles. Además, dada una rama N-way, una serie de sentencias if encontrará la ruta adecuada en O (N), mientras que una función virtual la encontrará en O (1). La instrucción de cambio puede ser O (N) u O (1) dependiendo de si está optimizada para una tabla de salto.
Uno de los mensajes más informativos que he visto en un tiempo que no conocía de antemano y que aún era fácilmente comprensible. –
Excelente respuesta, muchas gracias. Como no estoy planeando llamar a mis métodos en un círculo muy cerrado, no me preocuparé demasiado por esta sobrecarga.Gracias por la ayuda =) –
Anton Ertl mantiene una página de referencia útil (con código fuente) que incluye los costos directos y indirectos de envío de funciones para una buena variedad de procesadores: http://www.complang.tuwien.ac.at/forth/threading/ –