Mostrando entradas con la etiqueta rendimiento. Mostrar todas las entradas
Mostrando entradas con la etiqueta rendimiento. Mostrar todas las entradas

lunes, 8 de junio de 2009

Los 8 puntos de mejora del rendimiento

Wille Faler[1] propone en su blog 8 consejos para ayudarte a mejorar el rendimiento y la escalabilidad de tus sistemas, entre los que destacan la descarga de la base de datos, el uso de caché, y minimizar el tráfico de red.
  1. Descargar la base de datos. Mejor cuanto más lejos, no establezcas conexiones ni inicies transacciones a menos que sea estrictamente necesario. Y en los casos que así parezca, intenta buscar una alternativa.
  2. La caché marca la diferencia. Una buena caché descargará en gran medida la carga de la base de datos, especialmente en accesos de sólo lectura. Mejor en memoria que en disco y, aun así, mejor en disco que en una base de datos remota.
  3. Almacena en la caché objetos completos, y recupéralos con sus relaciones. Eso te garantizará disminuir la necesidad de consumo de CPU.
  4. No almacenes información de estado en la base de datos si no es necesario.
  5. Localiza, pon las cosas cerca de quien las necesite.
  6. Controla el acceso concurrente a recursos concretos. Si más de una petición necesita de un mismo cálculo para acceder a un recurso es mejor realizarlo una vez y hacer que las siguientes peticiones esperen para reutilizar los resultados.
  7. Usa procesos asícronos.
  8. Minimiza el tráfico de red ya que las comunicaciones serán mucho peores por red que en memoria.
Todo parece obvio pero no siempre se toman en cuenta, ¿no?


Enlaces

[1] http://faler.wordpress.com/2009/05/08/best-practices-for-scalable-high-performance-systems/

miércoles, 7 de mayo de 2008

Fácil pero... jmap, jps, jstack

Siempre que hay un problema serio tenemos que recurrir a la información ofrecida por una serie de utilidades que incluye "de serie" Java 5, jmap para la información en la memoria del proceso, jps para obtener las jvm corriendo en el sistema, y jstack para la traza de los hilos.

Por ejemplo, para obtener las jvm de la máquina hacemos:
emilio@silencio:~$ /opt/java5/bin/jps
21910 Jps
21801 Bootstrap
Después, la traza de los hilos:
emilio@silencio:~$ /opt/java5/bin/jstack 21801
Attaching to process ID 21801, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_08-b03
Thread 21949: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- org.apache.tomcat.util.threads.ThreadPool$MonitorRunnable.run() @bci=10, line=559 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=595 (Interpreted frame)
con el que, al menos, podremos atacar el problema con más conocimiento...

Por último, jugamos con la memoria, de más o menos interés dependiendo de las necesidades, generación permanente:
emilio@silencio:~$ /opt/java5/bin/jmap -permstat 21801
Attaching to process ID 21801, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_08-b03
finding class loader instances ..Unknown oop at 0x9d385848
Oop's klass is null
done.
computing per loader stat ..done.
please wait.. computing liveness.................................................................done.
class_loader classes bytes parent_loader alive? type

1211 2771016 null live
0x9f1d9a38 1 1408 0x9efec8e0 dead sun/reflect/DelegatingClassLoader@0xad392da0
0x9f1ace08 1 1424 0x9efec8e0 dead sun/reflect/DelegatingClassLoader@0xad392da0
0x9f061d58 1 1408 0x9efec8e0 dead sun/reflect/DelegatingClassLoader@0xad392da0
0x9f8773e0 58 172472 0x9effbcf8 live org/apache/catalina/loader/WebappClassLoader@0xad9d8da0
histograma:
emilio@silencio:~$ /opt/jdk1.5.0_08/bin/jmap -histo 21801
Attaching to process ID 21801, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_08-b03
Iterating over heap. This may take a while...
Unknown oop at 0x9d355648
Oop's klass is null
Object Histogram:

Size Count Class description
-------------------------------------------------------
5527864 44548 * ConstMethodKlass
3520376 43933 char[]
3210464 44548 * MethodKlass
2764288 67280 * SymbolKlass
2216472 4001 * ConstantPoolKlass
1657864 4774 byte[]
1640944 4001 * InstanceKlassKlass
1325072 3614 * ConstantPoolCacheKlass
1225368 51057 java.lang.String
690320 8629 java.lang.reflect.Method
685512 9521 java.lang.reflect.Field
655104 5685 int[]
428448 4463 java.lang.Class
405936 16914 java.util.HashMap$Entry

y el resumen:
emilio@silencio:~$ /opt/jdk1.5.0_08/bin/jmap -heap 21801
Attaching to process ID 21801, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 1.5.0_08-b03

using thread-local object allocation.
Mark Sweep Compact GC

Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 268435456 (256.0MB)
NewSize = 655360 (0.625MB)
MaxNewSize = 4294901760 (4095.9375MB)
OldSize = 1441792 (1.375MB)
NewRatio = 8
SurvivorRatio = 8
PermSize = 16777216 (16.0MB)
MaxPermSize = 67108864 (64.0MB)

Heap Usage:
New Generation (Eden + 1 Survivor Space):
capacity = 1245184 (1.1875MB)
used = 666696 (0.6358108520507812MB)
free = 578488 (0.5516891479492188MB)
53.54196648848684% used
Eden Space:
capacity = 1114112 (1.0625MB)
used = 638656 (0.60906982421875MB)
free = 475456 (0.45343017578125MB)
57.32421875% used
From Space:
capacity = 131072 (0.125MB)
used = 28040 (0.02674102783203125MB)
free = 103032 (0.09825897216796875MB)
21.392822265625% used
To Space:
capacity = 131072 (0.125MB)
used = 0 (0.0MB)
free = 131072 (0.125MB)
0.0% used
tenured generation:
capacity = 10674176 (10.1796875MB)
used = 10395440 (9.913864135742188MB)
free = 278736 (0.2658233642578125MB)
97.38868836339218% used
Perm Generation:
capacity = 20447232 (19.5MB)
used = 20255184 (19.316848754882812MB)
free = 192048 (0.1831512451171875MB)
99.06076284555289% used

Desde Java 6 podemos hacer cosas más interesantes con jmap + herramientas como visualvm... pero esa es otra historia.

lunes, 28 de abril de 2008

Rendimiento

Retomando un tema ya comentado por Martín hace algún tiempo, y sin entrar en las consideraciones que ya él realizó, los problemas de rendimiento de una aplicación no tienen por qué estar en la propia aplicación.

Supongamos una estructura tipo, con un servidor web (Apache httpd), un contenedor de servlets (Apache Tomcat), y una base de datos (MySQL), con una aplicación que hace uso de un datasource para la comunicación con la base de datos. Tenemos hasta cuatro puntos de ajuste que pueden causar, si están mal configurados, problemas serios de rendimiento.

Estudiemos el primero, tiempos de respuesta de la base de datos. Nuestro sistema debe responder en un tiempo razonable así que, tener accesos a la base de datos que no sean casi inmediatos no nos vale. Tiempos de respuesta superior al segundo son inaceptables.

El segundo, la configuración del pool de conexiones. El número de conexiones que debe gestionar debe ser realista. Como tengo más peticiones al servidor web, sumo más conexiones al pool... si la base de datos no lo soporta simplemente estás haciendo que su rendimiento decaiga. También configurar unos timeouts altos (jamás lo pongas como ilimitado) es inútil. Tiempos superiores a los 5000ms en este punto es absurdo. Mejor manda un error 500 con algún mensaje que luego comentaremos.

Conexiones al contenedor de servlets, Tomcat en nuestro ejemplo, es el tercero de los puntos. Volvemos a lo mismo, el número de peticiones que soporte (siempre peticiones dinámicas, un tomcat no está para servir elementos estáticos) debe ser ajustado a la realidad, y los timeouts, igual que para el pool, 5000ms son ya 5 segundos...

El último, Apache, cuidado con la memoria de cada hilo si usas php, cuidado con el número de conexiones persistentes, y vuelta a los timeouts, ¿de qué vale un timeout altísimo si no soportamos ni 5 segundos a que cargue una página?

Este post no te va a contar cómo configurar cada uno de los elementos, eso lo dejo para otro día, pero sí que has de tener en cuenta todos esos puntos, muy sencillos, antes de meterte en otros jaleos. Y recuerda, todos los servicios (base de datos, tomcat, y apache) requieren de una administración y configuración para entornos en producción, nunca es suficiente dejarlos tal cual se instalan.

viernes, 25 de abril de 2008

Retomando nuevamente el comienzo

Parece que empezar cosas se me está dando bien, y como dije en anteriores posts, en este blog espero escribir sobre temas relacionados con mi trabajo diario, fundamentalmente Java, aplicaciones web, rendimiento, escalabilidad, y cualquier cosa que me interese en el momento de enviar un post.