La mayoría de los desarrolladores dan por sentado que la optimización del rendimiento es compleja y requiere mucha experiencia y conocimiento. Bueno, no se puede decir que esto esté completamente mal. Optimizar su aplicación para un rendimiento óptimo no es una tarea fácil. Sin embargo, esto no significa que no pueda hacer nada si no tiene este conocimiento. Aquí hay 11 consejos y mejores prácticas fáciles de seguir para ayudarlo a crear una aplicación bien realizada.
La mayoría de las sugerencias son para Java. Pero hay varias sugerencias que son independientes del lenguaje y pueden aplicarse a todas las aplicaciones y lenguajes de programación. Antes de discutir técnicas de ajuste de rendimiento específicamente para Java, echemos un vistazo a los consejos generales.
1. No optimice hasta que sepa que es necesario
Este es probablemente uno de los consejos de ajuste de rendimiento más importantes. Debe seguir las mejores prácticas comunes e intentar implementar sus casos de uso de manera eficiente. Sin embargo, esto no significa que deba reemplazar cualquier biblioteca estándar o construir optimizaciones complejas antes de ser necesario.
En la mayoría de los casos, la optimización prematura no solo tomará mucho tiempo, sino que también dificultará el código de leer y mantener. Peor aún, estas optimizaciones generalmente no traen ningún beneficio, porque lo que pasa mucho tiempo optimizando es la parte no crítica de la aplicación.
Entonces, ¿cómo demuestra que necesita optimizar algo?
Primero, debe definir qué tan rápido es el código de su aplicación, por ejemplo, especificar un tiempo de respuesta máximo para todas las llamadas de API, o especificar el número de registros que se importan en un rango de tiempo específico. Una vez que haya hecho esto, puede medir qué partes de la aplicación son demasiado lentas para mejorar. Entonces, veamos el segundo truco.
2. Use el analizador para encontrar el cuello de botella real
Después de seguir la primera sugerencia y determinar que algunas partes de la aplicación necesitan una mejora, ¿entonces dónde comenzar?
Puede resolver el problema de dos maneras:
Consulte su código y comience con la parte que parece sospechosa o que siente que puede ser problemático.
O use el analizador y obtenga información detallada sobre el comportamiento y el rendimiento de cada parte del código.
Ojalá no necesite explicar por qué siempre debo seguir el segundo método.
Es obvio que un enfoque basado en el analizador le permite comprender mejor el impacto del rendimiento de su código y permitirle concentrarse en las partes más críticas. Si ha usado un analizador, debe recordar cuán sorprendido estaba de averiguar qué partes del código tenían problemas de rendimiento. Para ser honesto, mi primera suposición me ha llevado a la dirección equivocada más de una vez.
3. Cree un conjunto de pruebas de rendimiento para toda la aplicación
Este es otro consejo universal que puede ayudarlo a evitar muchos problemas inesperados que a menudo ocurren después de implementar mejoras de rendimiento en la producción. Siempre debe definir un conjunto de pruebas de rendimiento que pruebe toda la aplicación y ejecutarla antes y después de las mejoras de rendimiento.
Estas pruebas adicionales lo ayudarán a identificar los efectos secundarios funcionales y de rendimiento del cambio y se asegurarán de que no se causen daño a las buenas actualizaciones. Esto es especialmente importante si trabaja en componentes utilizados por varias partes diferentes de la aplicación, como bases de datos o cachés.
4. Primero trato con el cuello de botella más grande
Después de crear un conjunto de pruebas y analizar la aplicación utilizando el analizador, puede enumerar una variedad de problemas que deben abordarse para mejorar el rendimiento. Esto es genial, pero aún no responde a la pregunta de dónde debe comenzar. Puede concentrarse en soluciones de acción rápida o comenzar con las preguntas más importantes.
Los esquemas de acción rápida pueden ser atractivos al principio porque puede mostrar rápidamente el primer resultado. Pero a veces, es posible que deba convencer a otros miembros del equipo o a la gerencia de que el análisis de rendimiento lo vale, porque no hay ningún efecto en este momento.
Pero en general, recomiendo tratar primero los problemas de rendimiento más importantes. Esto le proporcionará las mayores mejoras de rendimiento y es posible que ya no necesite resolver algunos de estos problemas para cumplir con los requisitos de rendimiento.
Los consejos de ajuste de rendimiento comunes terminan aquí. Echemos un vistazo más de cerca a algunos consejos específicos de Java.
5. Use StringBuilder para conectar cadena programáticamente
Hay muchas opciones diferentes para conectar cadenas en Java. Por ejemplo, puede usar Simple + o + =, así como StringBuffer o StringBuilder.
Entonces, ¿qué método debes elegir?
La respuesta depende del código que conecta la cadena. Si está agregando nuevo contenido a una cadena programáticamente, por ejemplo en un bucle for, entonces debe usar StringBuilder. Es fácil de usar y ofrece un mejor rendimiento que StringBuffer. Pero recuerde que en comparación con StringBuffer, StringBuilder no es seguro de hilo y puede no ser adecuado para todos los casos de uso.
Solo necesita instanciar un nuevo StringBuilder y llamar al método Append para agregar una nueva parte a la cadena. Después de haber agregado todas las piezas, puede llamar al método ToString () para recuperar la cadena conectada.
El siguiente fragmento de código muestra un ejemplo simple. Durante cada iteración, este bucle convierte i en una cadena y la agrega a StringBuilder SB junto con un espacio. Entonces, al final, este código escribirá "Esta es una prueba0 1 2 3 4 5 6 7 8 9" en el archivo de registro.
StringBuilder sb = new StringBuilder ("Esta es una prueba"); para (int i = 0; i <10; i ++) {sb.append (i); sb.append ("");} log.info (sb.ToString ());Como puede ver en el fragmento de código, puede proporcionar el primer elemento de la cadena al constructor. Esto creará un nuevo StringBuilder que contiene la cadena proporcionada y la capacidad de 16 caracteres adicionales. Cuando agrega más caracteres al StringBuilder, el JVM aumentará dinámicamente el tamaño del StringBuilder.
Si ya sabe cuántos caracteres contendrá su cadena, puede proporcionar ese número a diferentes constructores para instanciar un StringBuilder con capacidad definida. Esto mejora aún más la eficiencia porque no requiere una expansión dinámica de su capacidad.
6. Use + para concatenar la cadena en una declaración
Cuando implementa su primera aplicación en Java, alguien puede haberle dicho que no debe usar + para conectarse a String. Si está concatenando cadenas en la lógica de la aplicación, esto es correcto. Las cadenas son inmutables, y los resultados de la concatenación de cada cadena se almacenan en un nuevo objeto de cadena. Esto requiere memoria adicional y ralentizará su aplicación, especialmente si concatena varias cadenas dentro de un bucle.
En estos casos, debe seguir el consejo 5 y usar StringBuilder.
Pero si solo divide la cadena en múltiples líneas para mejorar la legibilidad de su código, eso es diferente.
Consulta q = em.createQuery ("Seleccione A.ID, A.FirstName, A.LastName"
+ "Del autor A"
+ "Donde a.id =: id");
En estos casos, debe usar un simple + para concatenar su cadena. El compilador Java optimiza esto y realiza conexiones en el momento de la compilación. Entonces, en tiempo de ejecución, su código solo usará 1 cadena y no se requiere ninguna conexión.
7. Use primitivas tanto como sea posible
Otra forma fácil y rápida de evitar cualquier sobrecarga y mejorar el rendimiento de la aplicación es usar el tipo básico en lugar de su clase de envoltorio. Por lo tanto, es mejor usar int en lugar de entero y doble en lugar de doble. Esto permite que el JVM almacene los valores en la pila en lugar del montón para reducir el consumo de memoria y realizar un procesamiento más eficiente.
8. Trate de evitar BigInteger y BigDecimal
Dado que estamos discutiendo los tipos de datos, echemos un vistazo rápido a Biginteger y BigDecimal. En particular, este último es popular por su precisión. Pero hay un precio.
Biginteger y BigDecimal requieren más memoria que simple o doble y disminuirán significativamente todos los cálculos. Por lo tanto, si necesita precisión adicional, o los números superarán el largo alcance, es mejor pensarlo dos veces antes de hacerlo. Esta es probablemente la única forma en que necesita cambiar para resolver problemas de rendimiento, especialmente al implementar algoritmos matemáticos.
9. Primero verifique el nivel de registro actual
Esta sugerencia debería ser obvia, pero desafortunadamente, muchos programadores la ignoran en su mayoría al escribir código. Antes de crear un mensaje de depuración, siempre debe verificar el nivel de registro actual primero. De lo contrario, puede crear una cadena de mensaje de registro que se ignorará más adelante.
Aquí hay dos ejemplos negativos.
// no hagas thisLog.debug ("user [" + username + "] llamado Método X con [" + i + "]"); // o thisLog.debug (string.format ("User [%s] llamado Método X con [%d]", username, i));En ambos casos, realizará todos los pasos necesarios para crear un mensaje de registro sin saber si el marco de registro usará el mensaje de registro. Por lo tanto, es mejor verificar el nivel de registro actual antes de crear un mensaje de depuración.
// Do thisif (log.isdeBugeNabled ()) {log.debug ("user [" + username + "] llamado método x con [" + i + "]");}10. Use Apache Commons StringUtils.replace en lugar de string.replace
En términos generales, el método String. Replace funciona bien y es muy eficiente, especialmente cuando se usa Java 9. Sin embargo, si su aplicación requiere muchas operaciones de reemplazo y no se actualiza a la última versión de Java, entonces es necesario encontrar alternativas más rápidas y eficientes.
Hay una respuesta alternativa al método StringUtils.replace de Apache Commons Lang. Como Lukas Eder describió en una publicación de blog reciente, el método StringUtils.replace es muy superior al método String.Replace de Java 8.
Y solo requiere cambios menores. Es decir, agregue las dependencias Maven del proyecto Apache Commons Lang al pom.xml de la aplicación y reemplace todas las llamadas al método String.Replace con el método StringUtils.replace.
// reemplazar thisTest.replace ("prueba", "prueba simple"); // con thisStringUtilss.replace (prueba, "prueba", "prueba simple");11. Recursos costosos de caché, como conexiones de bases de datos
El almacenamiento en caché es una solución popular para evitar la ejecución repetida de fragmentos de código caros o comunes. La idea general es simple: es más barato reutilizar estos recursos que crear repetidamente nuevos recursos.
Un ejemplo típico es una conexión de base de datos en un grupo de caché. Las nuevas conexiones tardan en crear, lo que se puede evitar si reutiliza las conexiones existentes.
También puede encontrar otros ejemplos en el idioma Java en sí. Por ejemplo, el valor del método de la clase entera almacenan en caché entre -128 y 127. Se podría decir que crear un nuevo entero no es demasiado costoso, pero debido a que a menudo se usa, almacenar en caché los valores más utilizados también puede proporcionar beneficios de rendimiento.
Sin embargo, cuando considera el almacenamiento en caché, recuerde que las implementaciones de caché también pueden incurrir en sobrecarga. Debe gastar memoria adicional para almacenar recursos reutilizables, por lo que es posible que deba administrar cachés para que los recursos sean accesibles, así como eliminar recursos obsoletos.
Entonces, antes de comenzar a almacenar en caché de cualquier recurso, asegúrese de que la implementación del caché valga la pena, es decir, debe usarlos lo suficiente.
Resumir
Como puede ver, a veces no se necesita mucho trabajo para mejorar el rendimiento de su aplicación. La mayoría de las sugerencias en este artículo requieren un poco de esfuerzo para aplicarlas a su código.
Pero lo más importante son los trucos que no están relacionados con el lenguaje de programación que es:
No optimice el uso de analizadores para encontrar cuellos de botella reales antes de saber que es necesario. Primero trato con los cuellos de botella más grandes.
Lo anterior es todo el contenido compartido en este artículo sobre las técnicas de ajuste de rendimiento Java muy simples y fáciles de entender. Espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a este sitio:
Java implementa un código detallado para compartir funciones de la plataforma pública WeChat Momentos WeChat
Análisis comparativo de las instancias de rendimiento de la serialización nativa de Java y la serialización de KRyo
Exploración sobre si la subclase de programación de Java puede reescribir el método estático de la clase principal
Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!