Android: ¿Cuánto sobrecarga se genera ejecutando un método vacío?

He creado una clase para manejar mis salidas de la depuración de modo que no necesite despojar todas mis salidas del registro antes del lanzamiento.

public class Debug { public static void debug( String module, String message) { if( Release.DEBUG ) Log.d(module, message); } } 

Después de leer otra pregunta, he aprendido que el contenido de la instrucción if no se compilan si la constante Release.DEBUG es falsa.

Lo que quiero saber es cuánto sobrecarga se genera mediante la ejecución de este método vacío? (Una vez que la cláusula if se elimina no hay código en el método) ¿Va a tener algún impacto en mi aplicación? Obviamente el rendimiento es un gran problema cuando se escribe para teléfonos móviles = P

Gracias

Gary

    5 Solutions collect form web for “Android: ¿Cuánto sobrecarga se genera ejecutando un método vacío?”

    Mediciones realizadas en Nexus S con Android 2.3.2:

     10^6 iterations of 1000 calls to an empty static void function: 21s <==> 21ns/call 10^6 iterations of 1000 calls to an empty non-static void function: 65s <==> 65ns/call 10^6 iterations of 500 calls to an empty static void function: 3.5s <==> 7ns/call 10^6 iterations of 500 calls to an empty non-static void function: 28s <==> 56ns/call 10^6 iterations of 100 calls to an empty static void function: 2.4s <==> 24ns/call 10^6 iterations of 100 calls to an empty non-static void function: 2.9s <==> 29ns/call 

    controlar:

     10^6 iterations of an empty loop: 41ms <==> 41ns/iteration 10^7 iterations of an empty loop: 560ms <==> 56ns/iteration 10^9 iterations of an empty loop: 9300ms <==> 9.3ns/iteration 

    He repetido las mediciones varias veces. No se encontraron desviaciones significativas. Puede ver que el costo por llamada puede variar mucho dependiendo de la carga de trabajo (posiblemente debido a la compilación JIT), pero se pueden extraer 3 conclusiones:

    1. Dalvik / java apesta a optimizar el código muerto

    2. Las llamadas a funciones estáticas pueden optimizarse mucho mejor que las no estáticas (las funciones no estáticas son virtuales y deben buscarse en una tabla virtual)

    3. El coste en nexus s no es mayor que 70ns / call (es decir, 70 ciclos cpu) y es comparable con el coste de una iteración de bucle vacío (es decir, un incremento y una comprobación de condición en una variable local)

    Observe que en su caso el argumento string siempre será evaluado. Si realiza concatenación de cadenas, esto implicará la creación de cadenas intermedias. Esto será muy costoso e implica un montón de gc. Por ejemplo, ejecutar una función:

     void empty(String string){ } 

    Con argumentos como

     empty("Hello " + 42 + " this is a string " + count ); 

    10 ^ 4 iteraciones de 100 llamadas de este tipo toma 10s. Eso es 10us / call, es decir ~ 1000 veces más lento que sólo una llamada vacía. También produce gran cantidad de actividad del GC. La única manera de evitar esto es manualmente en línea la función, es decir, utilizar la instrucción >> if << en lugar de la llamada a la función de depuración. Es feo, pero la única manera de hacerlo funcionar.

    A menos que usted llame esto de dentro de un lazo profundamente anidado, no me preocuparía de él.

    Un buen compilador elimina todo el método vacío, lo que resulta en ninguna sobrecarga en absoluto. No estoy seguro de si el compilador de Dalvik ya hace esto, pero sospecho que es probable, al menos desde la llegada del compilador Just-in-time con Froyo.

    Ver también: Expansión en línea

    En términos de rendimiento, la sobrecarga de generar los mensajes que se pasan a la función de depuración va a ser mucho más grave ya que es probable que hagan asignaciones de memoria por ejemplo

     Debug.debug(mymodule, "My error message" + myerrorcode); 

    Que aún se producen incluso a través del mensaje se binned. Desafortunadamente, realmente necesita el "if (Release.DEBUG)" alrededor de las llamadas a esta función en lugar de dentro de la propia función si su objetivo es el rendimiento, y lo verá en un montón de código android.

    Esta es una pregunta interesante y me gusta el análisis @misiu_mp, así que pensé que lo actualizaría con una prueba 2016 en un Nexus 7 con Android 6.0.1. Aquí está el código de prueba:

     public void runSpeedTest() { long startTime; long[] times = new long[100000]; long[] staticTimes = new long[100000]; for (int i = 0; i < times.length; i++) { startTime = System.nanoTime(); for (int j = 0; j < 1000; j++) { emptyMethod(); } times[i] = (System.nanoTime() - startTime) / 1000; startTime = System.nanoTime(); for (int j = 0; j < 1000; j++) { emptyStaticMethod(); } staticTimes[i] = (System.nanoTime() - startTime) / 1000; } int timesSum = 0; for (int i = 0; i < times.length; i++) { timesSum += times[i]; Log.d("status", "time," + times[i]); sleep(); } int timesStaticSum = 0; for (int i = 0; i < times.length; i++) { timesStaticSum += staticTimes[i]; Log.d("status", "statictime," + staticTimes[i]); sleep(); } sleep(); Log.d("status", "final speed = " + (timesSum / times.length)); Log.d("status", "final static speed = " + (timesStaticSum / times.length)); } private void sleep() { try { Thread.sleep(10); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void emptyMethod() { } private static void emptyStaticMethod() { } 

    El sleep() se añadió para evitar el desbordamiento del búfer Log.d

    Jugué con él muchas veces y los resultados eran bastante consistentes con @misiu_mp:

     10^5 iterations of 1000 calls to an empty static void function: 29ns/call 10^5 iterations of 1000 calls to an empty non-static void function: 34ns/call 

    La llamada al método estático siempre fue ligeramente más rápida que la llamada al método no estático, pero parece que a) la brecha se ha cerrado significativamente desde Android 2.3.2 yb) todavía hay un costo para hacer llamadas a un método vacío, estático o no.

    Mirar un histograma de los tiempos revela algo interesante, sin embargo. La mayoría de la llamada, ya sea estática o no, tomar entre 30-40ns, y mirando de cerca a los datos que son prácticamente todos los 30ns exactamente.

    Introduzca aquí la descripción de la imagen

    Ejecutar el mismo código con bucles vacíos (comentando las llamadas al método) produce una velocidad promedio de 8ns, sin embargo, alrededor de 3/4 de los tiempos medidos son 0ns mientras que el resto es exactamente 30ns.

    No estoy seguro de cómo dar cuenta de estos datos, pero no estoy seguro de que las conclusiones de @ misiu_mp todavía se mantienen. La diferencia entre los métodos estáticos estáticos y no estáticos es despreciable, y la preponderancia de las mediciones es exactamente 30ns. Dicho esto, parecería que todavía hay un costo no nulo para ejecutar métodos vacíos.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.