studio reales proyectos programacion libro introducción incluye herramientas fundamentos fuente español código con avanzado aplicaciones c++ inline-functions

c++ - reales - libro de android studio en español pdf



¿Qué hay de malo con el uso de funciones en línea? (12)

Si bien sería muy conveniente usar funciones en línea en algunas situaciones,

¿Hay algún inconveniente con las funciones en línea?

Conclusión

Aparentemente, no hay nada de malo con el uso de funciones en línea.

¡Pero vale la pena señalar los siguientes puntos!

  • El uso excesivo de la línea puede hacer que los programas sean más lentos. Dependiendo del tamaño de una función, al alinearla puede aumentar o disminuir el tamaño del código. Alinear una función de acceso muy pequeña generalmente disminuirá el tamaño del código, mientras que una función muy grande puede aumentar drásticamente el tamaño del código. En los procesadores modernos, el código más pequeño generalmente se ejecuta más rápido debido al mejor uso de la memoria caché de instrucciones. - Pautas de Google

  • Los beneficios de velocidad de las funciones en línea tienden a disminuir a medida que la función aumenta de tamaño. En algún momento, la sobrecarga de la llamada de función se vuelve pequeña en comparación con la ejecución del cuerpo de la función, y se pierde el beneficio .

  • Hay algunas situaciones en las que una función en línea puede no funcionar:

    • Para una función que devuelve valores; si existe una declaración de devolución.
    • Para una función que no devuelve ningún valor; si existe una instrucción loop, switch o goto.
    • Si una función es recursiva -Fuente
  • La palabra clave __inline hace que una función esté enlineada solo si especifica la opción optimizar. Si se especifica optimizar, se __inline o no depende de la configuración de la opción del optimizador en línea. De forma predeterminada, la opción en línea tiene efecto cada vez que se ejecuta el optimizador. Si especifica optimizar, también debe especificar la opción noinline si desea __inline palabra clave __inline . -Fuente


También debe tener en cuenta que la palabra clave en línea es solo una solicitud. El compilador puede elegir no alinearlo, del mismo modo el compilador puede elegir hacer una función en línea que no definió como en línea si cree que vale la pena la compensación de velocidad / tamaño.

Esta decisión se basa generalmente en varias cosas, como la configuración entre optimizar la velocidad (evita la llamada a la función) y optimizar el tamaño (la alineación puede causar la saturación del código, por lo que no es ideal para grandes funciones repetidas).

con el compilador de VC ++ puede superar esta decisión utilizando __forceinline

SO en general: utilice en línea si realmente desea tener una función en un encabezado, pero en cualquier otro lado tiene poco sentido, porque si va a obtener algo de él, un buen compilador lo hará en línea para usted de todos modos.


Estoy de acuerdo con las otras publicaciones:

  • en línea puede ser superfluo porque el compilador lo hará
  • en línea puede hinchar su código

Un tercer punto es que puede obligarlo a exponer detalles de implementación en sus encabezados, por ejemplo,

class OtherObject; class Object { public: void someFunc(OtherObject& otherObj) { otherObj.doIt(); // Yikes requires OtherObj declaration! } };

Sin la línea, una declaración directa de OtherObject era todo lo que necesitabas. Con el en línea su encabezado necesita la definición de OtherObject.


La creación excesiva de funciones puede aumentar el tamaño del archivo ejecutable compilado, lo que puede tener un impacto negativo en el rendimiento del caché, pero hoy en día el compilador decide sobre la función en línea por sí mismo (dependiendo de muchos criterios) e ignora la palabra clave en línea.


Lo dudo. Incluso el compilador enumera automáticamente algunas funciones para la optimización.


Vale la pena señalar que la palabra clave en línea es solo una pista para el compilador. El compilador puede ignorar el en línea y simplemente generar código para la función en algún lugar.

El principal inconveniente de las funciones en línea es que puede aumentar el tamaño de su ejecutable (dependiendo del número de instancias). Esto puede ser un problema en algunas plataformas (por ejemplo, sistemas integrados), especialmente si la función en sí es recursiva.

También recomendaría hacer muy pequeñas las funciones en línea: los beneficios de velocidad de las funciones en línea tienden a disminuir a medida que la función aumenta de tamaño. En algún punto, la sobrecarga de la llamada de función se vuelve pequeña en comparación con la ejecución del cuerpo de la función, y se pierde el beneficio.


Como otros han mencionado, la palabra clave en línea es solo una pista para el compilador. De hecho, la mayoría de los compiladores modernos ignorarán por completo esta pista. El compilador tiene su propia heurística para decidir si alinea una función y, francamente, no quiere su consejo, muchas gracias.

Si realmente quieres hacer algo en línea, si realmente lo has perfilado y has mirado el desmontaje para asegurarte de que prevalece la heurística del compilador tiene sentido, entonces es posible:

  • En VC ++, use la palabra clave __forceinline
  • En GCC, use __attribute __ ((always_inline))

Sin embargo, la palabra clave en línea tiene un segundo propósito válido: declarar funciones en archivos de encabezado pero no dentro de una definición de clase. La palabra clave en línea es necesaria para decirle al compilador que no genere múltiples definiciones de la función.


Incrustar funciones más grandes puede hacer que el programa sea más grande, lo que da como resultado más errores de caché y lo hace más lento.

Decidir cuándo una función es lo suficientemente pequeña como para aumentar el rendimiento es bastante complicado. La Guía de estilo C ++ de Google recomienda solo funciones de alineación de 10 líneas o menos.


Hay un problema con en línea: una vez que definió una función en un archivo de encabezado (lo que implica en línea, ya sea explícito o implícito definiendo un cuerpo de una función miembro dentro de la clase) no hay una manera simple de cambiarlo sin obligar a los usuarios a recompilar (a diferencia de reenlazar). A menudo, esto causa problemas, especialmente si la función en cuestión está definida en una biblioteca y el encabezado es parte de su interfaz.


No sé si mi respuesta está relacionada con la pregunta, pero:

¡Ten mucho cuidado con los métodos virtuales en línea! Algunos compiladores erróneos (versiones anteriores de Visual C ++, por ejemplo) generarían código en línea para los métodos virtuales en los que el comportamiento estándar consistía en no hacer más que bajar al árbol de herencia y llamar al método apropiado.


  1. Como otras personas dijeron que la función en línea puede crear un problema si el código es grande. Como cada instrucción se almacena en una ubicación de memoria específica, la sobrecarga de la función en línea crea un código que toma más tiempo para ser exicho.

  2. hay algunas otras situaciones en las que la línea puede no funcionar

    1. no funciona en caso de una función recursiva.
    2. Es posible que tampoco funcione con la variable estática.
    3. tampoco funciona en caso de que haya un uso de un bucle, un interruptor, etc. o podemos decir eso con múltiples declaraciones.
    4. Y la función principal no puede funcionar como función en línea.

Entre otros problemas con las funciones en línea, que he visto muy sobreutilizado (he visto funciones en línea de 500 líneas), hay que tener en cuenta lo siguiente:

  • inestabilidad de construcción

    • Cambiar el origen de una función en línea provoca que todos los usuarios del encabezado recompilen
    • #include la fuga en el cliente. Esto puede ser muy desagradable si retrabaja una función en línea y elimina un encabezado usado que ya no se usa y en el que se ha basado algún cliente.
  • tamaño ejecutable

    • Cada vez que se incluye una línea en línea en lugar de una instrucción de llamada, el compilador debe generar todo el código de la línea. Esto está bien si el código de la función es corto (una o dos líneas), no tan bueno si la función es larga
    • Algunas funciones pueden producir mucho más código del que aparece al principio. En mi caso, es un destructor ''trivial'' de una clase que tiene muchas variables de miembros que no son pod (o dos o 3 variables de miembros con destructores algo desordenados). Se debe generar una llamada para cada destructor.
  • Tiempo de ejecución

    • esto es muy dependiente de su caché de CPU y bibliotecas compartidas, pero la ubicación de referencia es importante. Si el código que está insertando se almacena en la caché de la CPU en un lugar, un número de clientes puede encontrar el código y no sufrir una falta de memoria caché y la posterior recuperación de memoria (y peor, en caso de que ocurra, una recuperación del disco) . Lamentablemente, este es uno de esos casos en los que realmente necesita hacer un análisis de rendimiento.

El estándar de codificación en el que trabajo limita las funciones en línea a los simples setters / getters, y específicamente dice que los destructores no deben estar en línea, a menos que tenga mediciones de rendimiento para mostrar que la línea interna le otorga una ventaja notable.


Podría aumentar el tamaño del ejecutable, y no creo que los compiladores siempre los hagan en línea a pesar de que utilizó la palabra clave en línea. (¿O es al revés, como lo que dijo Vaibhav ? ...)

Creo que generalmente está bien si la función solo tiene 1 o 2 afirmaciones.

Editar: Esto es lo que dice el documento linux CodingStyle al respecto:

Capítulo 15: La enfermedad en línea

Parece haber una percepción errónea común de que gcc tiene una opción de aceleración mágica "hazme más rápido" llamada "en línea". Si bien el uso de inlines puede ser apropiado (por ejemplo, como un medio para reemplazar macros, ver el Capítulo 12), muy a menudo no lo es. El uso abundante de la palabra clave en línea conduce a un kernel mucho más grande, que a su vez ralentiza el sistema en su conjunto, debido a una mayor huella de icache para la CPU y simplemente porque hay menos memoria disponible para la memoria caché. Solo piensa en ello; una falta de memoria de página causa una búsqueda de disco, que tarda fácilmente 5 milisegundos. Hay MUCHOS ciclos de CPU que pueden entrar en estos 5 milisegundos.

Una regla práctica razonable es no poner en línea las funciones que tienen más de 3 líneas de código en ellas. Una excepción a esta regla son los casos en que se sabe que un parámetro es una constante de tiempo de compilación, y como resultado de esta constancia, usted sabe que el compilador podrá optimizar la mayor parte de su función en tiempo de compilación. Para un buen ejemplo de este último caso, consulte la función en línea kmalloc ().

A menudo, las personas argumentan que agregar funciones en línea a funciones que son estáticas y se usan una sola vez siempre es una ganancia, ya que no existe una compensación de espacio. Si bien esto es técnicamente correcto, gcc es capaz de delimitar estos automáticamente sin ayuda, y el problema de mantenimiento de eliminar el en línea cuando aparece un segundo usuario supera el valor potencial de la sugerencia que le dice a gcc que haga algo que hubiera hecho de todos modos.