lunes, 2 de junio de 2008

Javolution

http://javolution.org/

¿Operaciones de inserción en strings de orden logarítmico en lugar de lineal?

¿Alguien que por fin se acuerda de optimizar específicamente los marshallings/unmarshailling de XML?

Eso mola...

Se trata de una biblioteca de clases básicas, muchas de ellas "sustitutivas" de las que vienen en la biblioteca estándar del JDK, cuyo principal objetivo es el alto rendimiento y la predictibilidad (determinismo) del mismo. Principalmente pensada inicialmente para sistemas de tiempo real y empotrados, aunque como puede verse también puede ser de gran utilidad en sistemas servido con mucha concurrencia o necesidades de rendimiento y escalabilidad.

La biblioteca estándar del JDK tiene un problema general: está pensada para no dar problemas en ningún entorno, por lo que puede no ser la mejor solución siempre. Por ejemplo, la mayor parte de las clases son threadsafe, lo cual significa que por ejemplo la concatenación en un StringBuffer o el uso de una tabla de hash está lleno de regiones de exclusión mutua y uso de monitores. Siendo que en el 95% de los casos son completamente innecesarias debido a que hoy en día un desarrollador trabaja dentro de un framework, o genera código para un EJB, etc, y ese objeto sólo va a ser ejecutado por un thread en cada momento.

Por supuesto, con el tiempo Java ha evolucionado en dos líneas:

  • Por un lado cada revisión de la máquina virtual / Hotspot VM hace que se reduzca la penalización por el uso de monitores allá donde no hacían falta.
  • Por otro lado, poco a poco en el JDK se han ido introduciendo versiones "no sincronizadas". Por la propia filosofía de compatibilidad hacia atrás, el tema va quedando al menos "raro", pero es lo que hay. Por ejemplo:
    • java.uti.HashMap (que ofrece la misma funcionalidad que la java.util.Hashtable de toda la vida).
    • java.lang.StringBuilder por fin desde el JDK 1.6 supone una alternativa "no sincronizada" al infame java.lang.StringBuffer. (¿De verdad nadie se había dado cuenta hasta ahora que en el 99,999999% de las veces la concatenación de cadenas se usa en un contexto threadsafe?????)

El problema de separar así la API es que estás delegando en la capacidad, memoria, experiencia y entrenamiento del desarrollador. Mi experiencia dicta que "si quieres que algo se haga de una cierta forma, no des dos opciones para ello; en un 50% de los casos se utilizará la incorrecta". No sé si hay una ley para ello, o si no le ponemos un nombre. Claro que para que tenga éxito la postulación tenemos que poner mejor las cantidades 80-20 por algún lado ;-)

En esta línea llega Javolution. Me gusta, y mucho. Probablemente porque es lo que yo siempre he querido hacer, probablemente porque me he enamorado de su código fuente.

Pero tiene una pega, probablemente insalvable: en el fondo lo mismo que comento arriba: se trata de algo nuevo que aprender, no estándar y que los desarrolladores que hay en el mercado y entran nuevos a tu equipo no están habituados a utilizar. Es decir, mal rollo salvo que se utilice en un contexto muy concreto dentro de un producto o exclusivamente en las partes críticas de un proyecto.

También tiene otra pega que he sufrido yo en intentos similares anteriores: las siguientes revisiones de la JVM o del JDK pueden hacer inservibles parte de las optimizaciones, o que se optimicen las clases estándar más allá de la línea que ha podido seguir Javolution.

Y finalmente: hay que saber lo que está haciendo. Hay que "ayudar" a las optimizaciones de forma declarativa indicando contextos de trabajo... Y no me gusta tener la obligación de que todo desarrollador de un equipo sea un auténtico experto en rendimiento o cuncurrencia.

Más que reconmendable, sobre todo en sistemas de tiempo real, pero teniendo siempre presente que no existen los milagros (sino que lo importante es la suma de muchos pequeños detalles) y también en cuenta las reflexiones de arriba ("gato escaldado del agua fría huye").

Como muestra un botón: benchmarking de parsers XML --http://www.xml.com/pub/a/2007/05/09/xml-parser-benchmarks-part-1.html?page=2

En cualquier caso, mi conclusión es:

  • Utilizarlo sólo en los proyectos y contextos en que sea inevitable, o crítico
  • Muy interesante para conocerlo y aprender de por qué y cómo está hecho
  • Muy interesante para que los señores que desarrollan el JDK (ahora es Open Source así que debería estar más abierto a ideas frescas), así como implementadores de las APIs más comunes y equipos de desarrollo de servidores de aplicaciones varios
  • Muchas veces de nada serviría utilizarlo en nuestro proyecto, si no lo aplica el servidor de aplicaciones que hay por debajo, y que también habría que meterle mano para que realmente se note un cambio en la tendencia de respuesta o rendimiento.

Por cierto, que en la documentación de la API puede verse unos gráficos comparativos de tiempos de resupuesta de cada clase frente a su "competidora" en el JDK...


No hay comentarios: