A diferencia de la optimización de una infraestructura, optimizar una aplicación consiste en revisar los detalles de implementación y aplicar un montón de pequeños cambios donde generalmente cada uno tiene un pequeño impacto sobre el consumo de recursos y/o tiempo de respuesta. En este artículo no se trata el tema forma genérica, ni es una introducción sobre el proceso de búsqueda y corrección de bugs, para lo anterior es más útil el Taller de Pruebas de Carga y Optimización publicado en este mismo sitio.
Este artículo realmente está compuesto por un listado de recomendaciones específicas que deben ser tenidas en cuenta en el desarrollo de una aplicación. Las recomendaciones están divididas entre recomendaciones genéricas para Java, recomendaciones para JavaServer Faces, recomendaciones para bases de datos, entre otras.
- Recomendaciones Genéricas para Java.
- Recomendaciones para Aplicaciones Web.
- Recomendaciones para JavaServer Faces.
- Recomendaciones para Bases de Datos Oracle.
Recomendaciones Genéricas para Java
1. No usar System.out.println()
Recomendación Evitar el uso de System.out.println(), este es un recurso serializado y requiere el uso de I/O en cada llamado. |
Parámetros de configuración Si eliminar el código del proyecto resulta costoso, puede enviar la salida estándar del servidor a una salida nula (por ejemplo /dev/null en ambientes UNIX). |
Síntomas y Excepciones que caracterizan el problema * Tiempos de respuesta elevados. |
Bibliografía de Referencia * Performance Análisis for Java Web Sites. Capítulo 2. |
2. Métodos Transaccionales en EJBs.
Recomendación En EJBs marcar como transaccionales únicamente los métodos necesarios. |
Parámetros de configuración Modificar esta opción en el archivo ejb-jar.xml de cada EJB. Por ejemplo: <container-transaction> <method> <ejb-name>EJBEjemploTransaccional</ejb-name> <method-name>metodoDeConsulta</method-name> </method> <trans-attribute>NotSupported</trans-attribute> </container-transaction> |
Síntomas y Excepciones que caracterizan el problema
|
3. Sentencias Precompiladas.
Recomendación Usar al máximo sentencias de base de datos precompiladas a través de la clase PreparedStatement cuando ejecute sentencias SQL. Esto evita que la base de datos compile varias veces la misma consulta y agiliza le ejecución de la sentencia. |
Síntomas y Excepciones que caracterizan el problema * Tiempos de respuesta de base de datos elevados.
|
4. Paginar Resultados Grandes.
Recomendación Paginar los resultados extensos (más de 100 registros) de bases de datos. |
Parámetros de configuración Utilice alguna utilidad o limite los resultados de las consultas SQL. |
Síntomas y Excepciones que caracterizan el problema * Consumo de memoria de máquina virtual elevado.
|
5. Evitar el uso de colecciones sincronizadas.
Recomendación Evite el uso de colecciones sincronizadas como Hashtable o Vector, estas implementaciones tienen todos sus métodos sincronizados lo que implica que generan bloqueos incluso para las operaciones de lectura. En vez de ello utilice implementaciones más sofisticadas como ConcurrentHashMap o CopyOnWriteArrayList que sólo bloquean las operaciones que modifiquen el contenido del objeto. |
Parámetros de configuración A partir de la versión 5 del JDK se incluyen implementaciones para el manejo de la concurrencia, busque las equivalencias para los objetos usados antes de esta versión. |
Síntomas y Excepciones que caracterizan el problema * Incremento de los tiempos de respuesta ante peticiones concurrentes. |
Bibliografía de Referencia * Java Concurrency in Practice, sección 5.2. |
6. Maneje Adecuadamente las Conexiones con Bases de Datos.
Recomendación Las conexiones hacia base de datos son recursos finitos y costosos en términos de tiempos de respuesta; para causar el menor impacto en la aplicación haga caso de las siguientes recomendaciones:
|
Código de Ejemplo Manejo adecuado de una conexión: Connection conn = null; try { // Obténgala dentro del bloque try conn = ConnectionFactory.getConnection(); … //usando la conexión } catch (…) { // si es necesario. } finally { //Cierre siempre la conexión en un bloque de este tipo if ((conn != null) && (!conn.isClose)) { conn.close(); } } NUNCA pase como referencia el método que devuelve la conexión: consultarElementos(ConnectionFactory.getConnection()); //NUNCA haga esto |
Síntomas y Excepciones que caracterizan el problema * Aparece contínuamente un mensaje indicando que el servidor de aplicaciones cerró una conexión sin finalizar.
|
7. Use Cachés para Evitar Operaciones de Lectura en Disco.
Recomendación Si repetidamente necesita leer un archivo almacenado en disco, procure usar un caché para cargarlo en memoria y realizar las operaciones de lectura de esta forma. El acceso a disco es una operación costosa y si sólo necesita leer el archivo, el caché es una manera optimizada de hacerlo. Use cachés manuales como variables estáticas o librerías más avanzadas como Tangosol Coherence. |
Síntomas y Excepciones que caracterizan el problema * Problemas de escalabilidad.
|
8. Lectura de Parámetros desde Un Archivo.
Recomendación Abrir y cerrar un archivo es una operación sumamente costosa en términos de tiempo, evite ejecutar este tipo de operaciones de forma masiva. Si la aplicación lee parámetros desde un archivo, asegúrese que este se cargue una única vez en algún mecanismo de caché (puede ser una variable estática) y que sea desde ahí de donde se lean los valores. |
Código de Ejemplopublic CacheConfiguration() { initBundle(); } private ResourceBundle cacheBundle = null; private synchronized void initBundle() { if (cacheBundle == null) { cacheBundle = ResourceBundle.getBundle(CONFIG_FILE_NAME); } } public String getLoaderClass(String cacheName) { try { return cacheBundle.getString(cacheName.concat(SUFFIX_LOADER)); }catch (Exception e){ return null; } } public String getOnDemandLoader(String cacheName) { try { return cacheBundle.getString(cacheName.concat(SUFFIX_ON_DEMAND_LOADER)); } catch (Exception e) { return null; } } |
Síntomas y Excepciones que caracterizan el problema * Tiempos de respuesta elevados.
|
9. Verifique el Uso Correcto de Recursos Compartidos.
Recomendación Cuando use un recurso compartido ya sea a través de un patrón singleton o cargándolo desde algún caché verifique que este recurso no conserve algún estado por especialmente con el uso de atributos clase. En caso de tener algún conflicto con este recursos cree una copia usando el método clone(). |
Síntomas y Excepciones que caracterizan el problema * Errores inesperados ante peticiones concurrentes.
|
Recomendaciones para Aplicaciones Web
1. Evite al Máximo Almacenar Objetos en Sesión.
Recomendación Evite al máximo el almacenamiento de objetos en sesión. La memoria consumida por estos objetos no se libera rápidamente y puede generar OutOfMemoryError o tiempos elevados en recolección de basura. |
Parámetros de configuración * Hacer un uso adecuado de variables de instancia y de la sesión en los Backing Beans.
|
Síntomas y Excepciones que caracterizan el problema * Patrones de consumo y liberación de memoria que indican fugas.
|
2. Elimine la Sesión tan Rápido como sea Posible.
Recomendación Elimine la sesión tan rápido como sea posible para liberar la memoria consumida. |
Parámetros de configuración * En lo posible configure un timeout de sesión corto.
|
Síntomas y Excepciones que caracterizan el problema * OutOfMemoryError.
|
3. Optimice el Contenido de las Páginas para Disminuir el Consumo de Ancho de Banda.
Recomendación * Eliminar los tags ALT, DIR, AccessKey y Rich:tooltip y las etiquetas que no sean absolutamente necesarias en las páginas Web.
|
Parámetros de configuración Asegúrese de usar los encabezados HTTP como se indica continuación:
|
Síntomas y Excepciones que caracterizan el problema * Alto consumo de ancho de banda.
|
4. Use el tag <object> para los applets y configure los parámetros de caché.
Recomendación El tag <applet> está obsoleto, use <object> para insertar applets en las páginas Web y configure los parámetros para hacer caché de los recursos que no cambian frecuentemente. |
Parámetros de configuración Un ejemplo del uso del tag es: <OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" width="640" height="500" id="applet"> <PARAM name="code" value= "com.heinsohn.runt.common.impresion.applets.ImpresionReportesApplet.class" /> <PARAM name="cache_option" value="plugin" /> <PARAM name="cache_archive" value="../../AppletsImpresionDocumentos.jar, ../../lib/jasperreports-2.0.5.jar, ../../lib/jasperreports-2.0.5-applet.jar" /> <PARAM name="cache_version" value="1.0.0.1,1.0.0.0,1.0.0.0" /> <PARAM name="document" value="#{EstadisticaComportamientoVolumenSoatBean.reporte}" /> <COMMENT> <EMBED code= "com.heinsohn.runt.common.impresion.applets.ImpresionReportesApplet.class" width="640" height="500" id="applet" type="application/x-java-applet" cache_option="plugin" cache_archive= "../../AppletsImpresionDocumentos.jar, ../../lib/jasperreports-2.0.5.jar, ../../lib/jasperreports-2.0.5-applet.jar" cache_version="1.0.0.1,1.0.0.0,1.0.0.0" document="#{EstadisticaComportamientoVolumenSoatBean.reporte}" MAYSCRIPT="true"> <NOEMBED> Este navegador no tiene soporte para aplicaciones Java. </NOEMBED> </EMBED> </COMMENT> </OBJECT> Note especialmente los parámetros en rojo que indican al manejador de applets que haga caché de los archivos pasados en la opción "cache-archive". |
Síntomas y Excepciones que caracterizan el problema * Alto consumo de ancho de banda.
|
Recomendaciones para JavaServer Faces
1. Evite el uso de Bindings en páginas Web.
Recomendación No use bindings. Los objetos usados para hacer enlaces entre controles Web y clases de Java son objetos bastante pesados y dado que su uso es extensivo, estos elevan considerablemente el consumo de memoria. |
Síntomas y Excepciones que caracterizan el problema * Consumo excesivo de memoria.
|
2. Optimice el Consumo de Recursos de JavaServer Faces a través del Archivo web.xml.
Recomendación La optimización de JavaServer Faces a través de web.xml puede mejorar el consumo de ancho de banda y de memoria. Personalice los siguientes parámetros:
|
Síntomas y Excepciones que caracterizan el problema * Alto consumo de ancho de banda.
|
Referencias * http://www.waltercedric.com/java-j2ee-mainmenu-53/283-java-server-faces/1215-recommended-webxml-for-jsf.html |
Recomendaciones para Bases de Datos Oracle
1. Secuencias con Caché.
Recomendación Crear la secuencias con caché por defecto. |
Parámetros de configuración En la creación de la secuencia utilizar un caché con el número de peticiones concurrentes esperados. Usar la instrucción: create sequence <NOMBRE_SECUENCIA> incremental by 1 start with 1 noclycle cache <CACHE>. Dónde CACHE debe ser un valor aproximado al número de usuarios concurrentes esperados usando la secuencia. |
Síntomas y Excepciones que caracterizan el problema * Tiempos de respuesta elevados cuando aumenta el número de usuarios concurrentes. |
2. Evite el Uso de LIKE.
Recomendación Las consultas que se filtran con el operador LIKE pueden tener tiempos de respuestas muy elevados en tablas medianas/grandes. Evite el uso de este operador, procure usar el igual (=) y en cuanto sea posible use índices para las búsquedas en campos de texto. |
Síntomas y Excepciones que caracterizan el problema Tiempos de respuesta elevados en consultas a la base de datos. |
3. Evite el Uso de DISTINCT.
Recomendación Las consultas que usan el operador DISTINCT para eliminar resultados duplicados son muy costosas en términos de tiempo y CPU para grupos grandes de datos. Evite este operador en lo posible y procure mejor realizar filtros y joins entre tablas de forma que las consultas no devuelvan valores duplicados. |
Síntomas y Excepciones que caracterizan el problema * Tiempos de respuesta elevados en consultas a la base de datos. |
4. Cree Índices con los Campos Usados como Filtros en los y con los Campos usados para Joins entre Tablas.
Recomendación Los índices mejoran considerablemente el desempeño de las sentencias SQL. Cree índices para los campos que se usen como filtros en las condiciones WHERE y créelos también para los campos que se usan en los join entre tablas. Cuando no esté seguro si una consulta está usando un índice use la sentencia set autotrace traceonly explain para hacer un análisis detallado. En SQL Plus únicamente ejecute la consulta y verá el plan de ejecución, en SQL Developer ingrese la consulta y presione F10 para hacer el análisis respectivo. |
Síntomas y Excepciones que caracterizan el problema * Tiempos de respuesta elevados en consultas a base de datos.
|
5. Limitar Valores para la Condición IN.
Recomendación Al usar una condición del tipo IN (a, b, c, …) tenga cuidado en no sobrepasar los mil valores pasados como parámetros a la condición porque el motor devolverá un mensaje de error. Esto es especialmente útil cuando los valores que se usarán como parámetros en la condición provienen de una consulta realizada previamente. |
Síntomas y Excepciones que caracterizan el problema * Error: "ORA-01795: el número máximo de expresiones en una lista es 1000". |