Buscar..


Enfoque general

Internet está repleto de consejos para mejorar el rendimiento de los programas Java. Quizás el consejo número uno sea la conciencia. Eso significa:

  • Identificar posibles problemas de rendimiento y cuellos de botella.
  • Utilizar herramientas de análisis y pruebas.
  • Conocer buenas prácticas y malas prácticas.

El primer punto se debe hacer durante la etapa de diseño si se habla de un nuevo sistema o módulo. Si se habla de código heredado, las herramientas de análisis y prueba entran en escena. La herramienta más básica para analizar el rendimiento de su JVM es JVisualVM, que se incluye en el JDK.

El tercer punto es principalmente sobre la experiencia y la investigación extensa, y por supuesto, consejos crudos que se mostrarán en esta página y otras, como esta .

Reduciendo cantidad de cuerdas

En Java, es demasiado "fácil" crear muchas instancias de String que no son necesarias. Esa y otras razones pueden hacer que su programa tenga muchas cadenas que el GC está ocupado limpiando.

Algunas formas en las que podrías estar creando instancias de String:

myString += "foo";

O peor aún, en un bucle o recursión:

for (int i = 0; i < N; i++) {
    myString += "foo" + i;
}

El problema es que cada + crea una nueva Cadena (generalmente, ya que los nuevos compiladores optimizan algunos casos). Se puede hacer una optimización posible utilizando StringBuilder o StringBuffer :

StringBuffer sb = new StringBuffer(myString);
for (int i = 0; i < N; i++) {
    sb.append("foo").append(i);
}
myString = sb.toString();

Si crea cadenas largas con frecuencia (por ejemplo, SQL), use una API de construcción de cadenas.

Otras cosas a considerar:

  • Reducir el uso de replace , substring , etc.
  • Evite String.toArray() , especialmente en el código de acceso frecuente.
  • Las impresiones de registro que están destinadas a ser filtradas (debido al nivel de registro, por ejemplo) no deben generarse (el nivel de registro debe verificarse de antemano).
  • Utilice bibliotecas como esta si es necesario.
  • StringBuilder es mejor si la variable se utiliza de manera no compartida (a través de hilos).

Un enfoque basado en la evidencia para el ajuste de rendimiento de Java

Donald Knuth a menudo es citado diciendo esto:

"Los programadores pierden enormes cantidades de tiempo pensando o preocupándose por la velocidad de las partes no críticas de sus programas, y estos intentos de eficiencia en realidad tienen un fuerte impacto negativo cuando se consideran la depuración y el mantenimiento. Debemos olvidar las pequeñas eficiencias, por ejemplo 97% del tiempo : la optimización prematura es la raíz de todo mal. Sin embargo, no debemos dejar pasar nuestras oportunidades en ese 3% crítico ".

fuente

Teniendo en cuenta este sabio consejo, este es el procedimiento recomendado para optimizar programas:

  1. En primer lugar, diseñe y codifique su programa o biblioteca con un enfoque en la simplicidad y la corrección. Para empezar, no dediques mucho esfuerzo al rendimiento.

  2. Llegue a un estado de trabajo y (idealmente) desarrolle pruebas unitarias para las partes clave del código base.

  3. Desarrollar una prueba de rendimiento de nivel de aplicación. El punto de referencia debe cubrir los aspectos críticos de rendimiento de su aplicación y debe realizar una serie de tareas que son típicas de cómo se usará la aplicación en producción.

  4. Medir el rendimiento.

  5. Compare el rendimiento medido con sus criterios para determinar qué tan rápido debe ser la aplicación. (Evite criterios poco realistas, inalcanzables o no cuantificables como "lo más rápido posible".)

  6. Si ha cumplido con los criterios, PARE. Tu trabajo está hecho. (Cualquier esfuerzo adicional es probablemente una pérdida de tiempo.)

  7. Perfile la aplicación mientras ejecuta su prueba de rendimiento.

  8. Examine los resultados de la creación de perfiles y elija los "hotspots de rendimiento" más grandes (no optimizados); Es decir, las secciones del código donde la aplicación parece estar gastando más tiempo.

  9. Analice la sección del código del hotspot para tratar de entender por qué es un cuello de botella y piense en una manera de hacerlo más rápido.

  10. Implementar eso como un cambio de código propuesto, probar y depurar.

  11. Vuelva a ejecutar el punto de referencia para ver si el cambio de código ha mejorado el rendimiento:

    • En caso afirmativo, vuelva al paso 4.
    • Si No, abandone el cambio y vuelva al paso 9. Si no está progresando, elija un punto de acceso diferente para su atención.

Eventualmente, llegará a un punto en el que la aplicación es lo suficientemente rápida o ha considerado todos los hotspots importantes. En este punto es necesario detener este enfoque. Si una sección del código consume (por ejemplo) el 1% del tiempo total, incluso una mejora del 50% solo hará que la aplicación sea un 0,5% más rápida en general.

Claramente, hay un punto más allá del cual la optimización del punto de acceso es una pérdida de esfuerzo. Si llegas a ese punto, debes adoptar un enfoque más radical. Por ejemplo:

  • Mira la complejidad algorítmica de tus algoritmos centrales.
  • Si la aplicación pasa mucho tiempo recolectando basura, busque formas de reducir la tasa de creación de objetos.
  • Si las partes clave de la aplicación son CPU intensivas y de un solo hilo, busque oportunidades para el paralelismo.
  • Si la aplicación ya tiene varios subprocesos, busque cuellos de botella de concurrencia.

Pero siempre que sea posible, confíe en las herramientas y la medición en lugar del instinto para dirigir su esfuerzo de optimización.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow