Cualquier documentación sobre la optimización de Android: JAVAC vs JIT vs Dalvik

Tengo que pensar mucho sobre la optimización en una aplicación de Android por primera vez.

He buscado, pero cuanto más busco, más me confundo. ¿Alguien sabe de buena documentación para describir cómo cada uno de los componentes de Java y JVM optimiza el código de bytes WRT JAVAC y el código de bytes Dalvik? ¿La mayor parte lo hizo Dalvik y, por lo tanto, está "en caja negra" lejos de mí? ¿Vale la pena mirarlo?

Algunos ejemplos triviales.

SharedPreferences settings = getSharedPreferences(MY_PREFERENCES, MODE_PRIVATE);
SharedPreferences.Editor prefEditor = settings.edit();
prefeditor.putString("FOO", "BAR"); 
prefEditor.commit();

vs

getSharedPreferences(MY_PREFERENCES, MODE_PRIVATE).settings.edit().putString("FOO","BAR").commit();

o

int a, b, c;

a = 2;
b = 3;

c = sum(a,b);

int sum(int x, int y){return x + y;}

vs

c = a + b;

Mi razón para preguntar es entender la compensación entre legibilidad y mantenibilidad y rendimiento. Sé que la respuesta estándar es "medirlo", pero estoy tratando de ir más allá y pensar de antemano dónde puedo obtener rendimiento en lugar de tener que volver a código complejo y refactorizar en función de las métricas. Por supuesto, mediré y perfilaré de todos modos, pero mi pregunta es sobre la comprensión.

¡Soy lo suficientemente abierto como para aceptar "ni siquiera vaya allí, escriba, mida y sea condenado"!

Gracias por cualquier idea.

Respuesta 1

Para una aplicación de Android, su código pasa por 2 pases de compilación / optimización. El primero lo realiza javac, cuando compila el código java en el código de bytes java. El segundo es realizado por dx, cuando traduce el bytecode de java a dalvik bytecode.

No estoy familiarizado con ninguna documentación que describa las optimizaciones realizadas por ninguno de los dos. Pero ambos son de código abierto (a través de openjdk, para javac), por lo que teóricamente podrías examinar ambos para tener una idea de las optimizaciones que hacen.

Sin embargo, sus ejemplos realmente no tienen nada que ver con las optimizaciones de nivel de compilador. No creo que saber cómo, por ejemplo, dx asigne registros de manera óptima, lo ayude a comprender cómo escribir un código Java eficaz.

Para los dos conjuntos de ejemplos que menciona, sugeriría probar 2 cosas en ambos conjuntos de ejemplos.


1. Desmontar

Lo primero sería desmontar el código de bytes de Dalvik y observar las diferencias. Simplemente contar las instrucciones no necesariamente le dirá nada, pero en algunos casos está claro que una es más rápida que la otra.

Por ejemplo, en su primer conjunto de ejemplos, el código de bytes para ambos fragmentos es casi idéntico, con la excepción de que el segundo fragmento contiene una instrucción adicional. Por lo tanto, el primer fragmento es claramente más eficaz, aunque sería una diferencia de rendimiento extremadamente menor.

invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences$Editor;->putString(Ljava/lang/String;Ljava/lang/String;)Landroid/content/SharedPreferences$Editor;
invoke-interface {v0}, Landroid/content/SharedPreferences$Editor;->commit()Z

vs.

invoke-interface {v0, v1, v2}, Landroid/content/SharedPreferences$Editor;->putString(Ljava/lang/String;Ljava/lang/String;)Landroid/content/SharedPreferences$Editor;
move-result-object v0
invoke-interface {v0}, Landroid/content/SharedPreferences$Editor;->commit()Z

Esta instrucción adicional tiene sentido si observa de cerca los dos fragmentos de Java. En el primero, se ignora el valor de retorno de putString y se invoca commit en el mismo valor que usted llamó a putString. Mientras que en el segundo fragmento, clone () se llama al valor devuelto por putString (), que requiere una operación adicional en el código de bytes dalvik para guardar el valor devuelto. A saber, la instrucción adicional de mover-resultado-objeto que ves allí.

Nosotros, como programadores, sabemos que el valor de retorno del método putString es el mismo objeto al que se está llamando. Sin embargo, el compilador no puede saberlo ni asumirlo.


2. Medida

La segunda cosa que puedes hacer es, como mencionas, realmente perfilarlos y medir el rendimiento. Después de un tiempo, debe comenzar a tener una idea de los tipos de cosas que puede hacer para mejorar el rendimiento.

Respuesta: 2

Estoy tratando de codificar una Cadena usando el cifrado XOR y uso una matriz de bytes como clave: Cadena encodedString = myString XOR myKey No tengo mucha experiencia con la criptografía, así que no he encontrado una manera ...

He escrito este código para la importación de servlets java.io. *; import javax.servlet. *; import javax.servlet.http. *; public class Httpservlet1 extiende HttpServlet {public void doGet (...

Este es mi intento de hacer un mapa de cubos. glDisable (GL_TEXTURE_2D); glEnable (GL_TEXTURE_CUBE_MAP); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); ...

Tengo un proyecto Java con algunas pruebas de Cucumber y algunas pruebas regulares de JUnit, administradas por Maven. Quiero ejecutar las pruebas en Jenkins, usando Docker, así que escribí este Jenkinsfile: pipeline {agent {...