| Inicio | Perfil | Servicios | Offshore | Recursos | Mapa del sitio | Contáctenos |          
Artículo "Buenas prácticas en J2EE. Segunda parte."

Este artículo contiene la segunda parte de un informe que explica técnicas de gran utilidad para el desarrollo con la plataforma J2EE. Aplicando estas técnicas, podemos disminuir la dificultad y el costo de este tipo de desarrollo y mejorar el rendimiento, calidad, flexibilidad y escalabilidad de los sistemas resultantes.



Resolución de fugas

Para resolver los problemas de memoria, se deberían seguir los siguientes pasos:

  • Reproducir el problema. El primer paso (y el más importante) es crear un caso de prueba que reproduzca el problema. Para ello, puede comenzarse activando la recolección de basura después de ejecutar los casos de prueba. Cuando se examine el uso total de memoria respecto al tiempo, se formará un gráfico con picos y valles. Los picos ocurren antes de que el sistema active la recolección de basura. Los valles aparecen después de la recolección de basura y representan el uso verdadero de memoria en el sistema. Si los mínimos en los valles aumentan a un ritmo constante, como en la figura 3, se ha encontrado una fuga de memoria.

  • Figura 3. El eje vertical representa el uso de memoria y el horizontal, el tiempo. El aumento en los valles entre recolecciones de basura (GC) indica una fuga.

  • Aislar el problema. Después de reproducir el problema, se debe intentar aislar el problema acotando el caso de prueba. Con frecuencia, se encuentra la fuga de esta forma, sin necesidad de más investigación.

  • Encontrar los objetos que molestan. El siguiente paso es usar un perfilador de memoria para localizar los objetos en memoria en los que se encuentra la fuga. Así, se comienza identificando bloques de memoria anormalmente grandes. Entonces, se comprueba el número de instancias de estos bloques y, a continuación, se activa la recolección de basura para los mismos, volviendo a contar el número de instancias de nuevo. Así se puede determinar si el sistema está liberando los objetos como debería.

  • Encontrar y reparar referencias a esos objetos. Cuando se ha identificado el objeto causante de la fuga, se pueden encontrar referencias al mismo y repararlas, lo que implica asignarlas a null o bien realizar otros pasos de limpieza (cerrar un archivo, eliminar una referencia de una colección, etc.). La limpieza debería realizarse en un bloque finally y no en el cuerpo principal de un método, para asegurarse de que se ejecuta incluso cuando las excepciones interrumpen la ejecución del programa.

  • Prevenir futuros casos del problema. Cuando sea posible, se deberían eliminar las causas de los problemas que causaron las fugas para evitar que se repitan en el futuro.

6.3. Buena práctica número 17. Concéntrese en las prioridades

Una forma de la regla 80/20 dice que, típicamente, 80% de la ejecución de un programa ocurrirá en un 20% del código. Por ello, es importante concentrar los recursos de desarrollo en las áreas que probablemente tengan un mayor impacto sobre el rendimiento. Para ello, debemos considerar:

  • El análisis de puntos calientes (Hot spot analysis) determina las secciones de código más activas para que los programadores concentren en ellas sus esfuerzos de optimización.

  • Las medidas de rendimiento pueden localizar casos de prueba que son críticamente lentos de forma que pueda variar la ejecución para que pase por las secciones de código con mayor importancia en el rendimiento, con el fin de poderlo optimizar.

  • La automatización de las pruebas de rendimiento permite establecer criterios sólidos de rendimiento para los casos de prueba y resolver problemas cuando se violan esos criterios. Para ello, se puede usar JUnitPerf (http://www.clarkware.com/software/JUnitPerf.html) o cualquier herramienta de automatización de pruebas de rendimiento.

La clave de una afinación efectiva es una asignación eficiente de recursos. Es decir, se debería invertir la mayor parte del tiempo en afinar las áreas de la aplicación que producirán el mayor beneficio. Lo contrario también es cierto: no se debería invertir tiempo intentando optimizar cada elemento de código que se escribe, excepto si se sabe que es crítico para el rendimiento. Esto no quiere decir que se deba escribir código descuidado, sino que debe usarse el código más simple que funcione, como mínimo hasta que las pruebas manuales o automáticas de rendimiento confirmen que es necesario optimizarlo.  

 
 

Ir a la página: 1   2   3   4   5   6   7   8   Siguiente >>

 Versión para imprimir

 

 

| Inicio | Perfil | Servicios | Offshore | Recursos | Mapa del sitio | Contáctenos|