miércoles, 24 de diciembre de 2008

Samsung Omnia

Finalmente me decanté por el Samsung Omnia de Vodafone. Las otras opciones eran, como no, iphone de Movistar, HTC HD de Movistar, o HTC Diamond de Vodafone (Android aún no es opción lamentablemente).

La decisión ha sido dura y política, no por características del terminal ni usabilidad sino por temas económicos y de politica de operador y fabricante.

¿Cómo puede hacer eso Movistar? ¿Por qué quiere meter la pata siempre con esas tarifas?

En fin, dejé a un lado la experiencia de usuario y me decanté por Samsung Omnia + Windows Mobile 6.1 + Vodafone España, con buenas sensaciones generales y alguna decepción con Vodafone, siempre asumiendo que tengo un teléfono con un SO no pensado para teléfonos.

jueves, 8 de mayo de 2008

Grupos de usuarios de javahispano en redes profesionales

Desde hace algún tiempo JavaHispano tiene presencia (en forma de grupos) en dos de las aplicaciones de networking laboral más importantes, LinkedIn y Xing.

Las direcciones para apuntarse en los grupos son:

Grupo en Xing: http://www.xing.com/group-20325.f5fa94
Grupo en LinkedIn: http://www.linkedin.com/e/gis/56889/224CFE6B2C0F

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

Quién me mira, quién está ahí...

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.

Tras tres post...

Hace sólo un día que empecé a escribir en mi blog de javaHispano y he decidido moverlo aquí. Los motivos, simplemente el tiempo y la facilidad que me ofrece blogger... una pena porque me gustaba el hecho de tenerlo alojado bajo weblogs.javahispano.org pero esta interfaz es más sencilla.

Como dije allí, vamos a ver cuánto tiempo seré capaz de mantener el blog...