MOISESDANIEL.COM
|
|
Ingeniero Informático, y…
aprendiz de casi todo. |
Rendimiento de las
Aplicaciones Web en Java.
2005-02-06.
© Moisés D. Díaz. www.moisesdaniel.com
1.-
Introducción.
2.- Qué
‘tunear’.
3.- Cuidar del recurso más escaso.
4.- Ultimo
consejo.
0.- Nota previa.
El desarrollo de portales web es mi principal trabajo, y decidí que el tema
del rendimiento tenía una gran importancia en este ámbito. Lo que aquí presento
no son más que algunas reflexiones particulares y algunas lecciones aprendidas
que he ido reflejando en mi Blog.
1.- Introducción.
Una de las leyes más importantes en este tema es que: “la velocidad de un sistema la determina su elemento más lento”
En el caso de los sistemas webs no siempre es fácil saber qué elemento es
el más lento, ya que en los diferentes usos de un sistema no siempre están
implicados todos los componentes que lo forman.
Lo que sí debemos tener claro es que prácticamente en cualquier sistema se
cumplirá la ley de Pareto, por lo que el 80% de las interacciones con el
sistema web se concentrará en un 20% de los elementos del mismo. Por lo tanto,
centrarnos en los elementos más usados y en los componentes que lo forman es
uno de los primeros pasos a dar en el estudio del rendimiento de un sistema.
Debemos asegurarnos que los elementos más significativos de una aplicación
web tienen un rendimiento aceptable.
2.- Qué
‘tunear’.
Todos los sistemas se encuentran con 3 recursos limitados:
-
Capacidad
de proceso de
-
Memoria.
-
Velocidad
de los sistemas de entrada/salida.
Hoy en día el tunning de las aplicaciones sigue siendo algo bastante
complejo.
En entornos como la web, en los que existen concurrentemente una gran cantidad
de procesos haciendo uso de un conjunto limitado de recursos no es nada
sencillo saber en cada momento qué pieza del sistema es la que está fallando (o
que no está funcionando tan bien como debería).
Lo lógico es iniciar el análisis de rendimiento haciendo pruebas de carga
sobre las páginas o casos de uso más frecuentes de nuestro sistema.
Para esto existen multitud de aplicaciones como por ejemplo Apache JMeter
que te permiten testear la aplicación web simulando un número grande de
usuarios e incluso puedes programar scripts (o configurarlo) para que el
comportamiento de cada uno de estos tenga cierta complejidad.
El resultado de una prueba de carga suele ser una gran cantidad de
resultados numéricos y gráficos que nos darán una imagen del rendimiento de
nuestra aplicación web.
|
|
Imaginemos que detectamos que el rendimiento no es el adecuado, que tenemos
problemas. La prueba de carga te da una visión ‘de caja negra’ sobre los problemas
de la web, y bucear en el código, haciendo seguimientos en el mismo, te
empantana en mil detalles. Creo que una aproximación más rentable es centrarse
en los diferentes componentes del sistema. Obtener datos de cada uno de ellos
en esas pruebas de carga, y luego centrarse en los que puedan resultar más
problemáticos. La máxima de dividir para conquistar parece que tiene bastante
sentido aquí.
|
|
Respecto a la memoria, veo dos patrones opuestos pero con sentido:
-
Uno,
duplicar recursos compartidos (a través de técnicas como la clonación), y
dárselos a cada uno de los usuarios (sesiones). Esto en un principio nos
permite que los usuarios no tengan que esperar a la liberación de los recursos
mientras los están usando otros. Implica un mayor uso de memoria. A esto lo
denominaremos patrón ‘Duplica-Recursos’.
-
Dos,
eliminar recursos duplicados en diferentes usuarios y hacerlos comunes para
todos (ponerlos a nivel de contexto). Esta técnica nos permite ahorrar memoria
(recurso que puede sernos fundamental), pero hace que los usuarios puedan
experimentar tiempos de espera mientras otros usuarios usan los recursos
compartidos. A esto lo denominaremos ‘Comparte-Recursos’.
¿Cuál es la técnica que más nos conviene? Pues depende del recurso en sí, e
incluso del tipo o perfil de nuestra aplicación web.
Si estamos desarrollando un portal con numerosísimas visitas, más bien
cortas, y en las que no es necesario mostrar información demasiado ‘customizada’
para el usuario, lo lógico sería tener sesiones poco costosas, que se creen
rápido, es decir aplicar el patrón ‘Comparte-Recursos’.
En caso contrario, el patrón ‘Duplica-Recursos’ quizás sea el más
apropiado, ya que desde luego suele ser más limpio en cuanto a desarrollo y más
sencillo ya que prácticamente no tenemos que tener en cuenta la concurrencia.
Monitorizar la máquina virtual puede ayudarnos
bastante. Desgraciadamente muchos servidores web no tienen este tipo de
funcionalidad (yo lo hecho de menos en el Tomcat), pero sí tenemos como mínimo
dos opciones:
-
Recurrir
a nuestro querido Java más básico.
o
Objeto System usando su primitiva CurrentTimeMilliseconds() . Podemos tomar
medidas antes y después de ejecutar cualquier trozo de código y ver por lo
tanto el coste temporal que tiene.
o
Objeto
Runtime, usando sus primitivas freeMemory() y totalMemory() para obtener
medidas de la cantidad de memoria del sistema que se está usando.
-
Recurrir
a nuestro entorno de desarrollo. Yo suelo programar usando Oracle JDeveloper
(que por cierto, me parece bastante bueno). Este entorno te da la posibilidad
de ejecutar las aplicaciones Java sacándote toda una serie de datos de tiempo
de cpu y memoria consumida.
|
|
Respecto a los sistemas de entrada/salida tenemos que tener en cuenta que
son costosísimos. Por lo que hay que cuidar los sistemas de Log que podamos
tener implementados para que no estén continuamente escribiendo en disco
mientras se ejecuta la aplicación web.
3.- Cuidar del recurso más escaso.
Evitar el congelamiento de nuestra web: Cuidar del recurso más escaso.
Como decíamos antes, todos los sistemas se encuentran con 3 recursos
limitados:
-
Capacidad
de proceso de
-
Memoria.
-
Velocidad
de los sistemas de entrada/salida.
El recurso más escaso depende totalmente del contexto en el que nos encontremos.
Si estuviésemos en un desierto probablemente el recurso más escaso (o al menos más valioso) sería el agua, elemento que casi no cuesta nada en muchas otras circunstancias.
Y hay que tener claro que en el ámbito de las aplicaciones web el contexto de ejecución cambia con la carga del servidor.
Dependiendo por tanto del perfil que tenga nuestro web (me refiero a su uso) tendremos que procurar minimizar el impacto que puede ocasionar al sistema la escasez de los recursos compartidos que puedan resultar más escasos (o más sensibles a la escasez), porque estos se convierten en auténticos cuellos de botellas que pueden llevar a que toda la aplicación web funcione realmente mal.
Un ejemplo: Si hacemos un uso muy intensivo de la base de datos este es un posible cuello de botella.
Una técnica para mejorar el rendimiento de este tipo de aplicaciones consiste precisamente en limitar el uso del recurso más escaso, por ejemplo cacheando información de tal forma que no tengamos que acceder a la base de datos para obtenerla.
4.- Último
consejo.
Como último apunte dejar constancia de la importancia de hacer pruebas y
obtener datos: dicen que sin medida no hay ciencia, y probablemente tampoco
ingeniería.
© Moisés
D. Díaz. http://www.moisesdaniel.com/, email: md (at) moisesdaniel (.) com. All Rights Reserved. RSS