Transformaciones XSL (III): No es oro todo lo que reluce.
Una vez escuche a alguien decir, que todo proyecto informático que se precie de cierta complejidad "tiene gato encerrado", está esperándote y cuando menos te lo esperas .... salta a por ti
Pues bien, el uso de Translets no es una excepción.
El problema
En una situación de producción con elevada concurrencia (el caso aquí descrito se produjo en un entorno real cuando más de 2.000 usuarios estaban conectados de forma simultánea), según de que forma se haga uso de las transformaciones proporcionadas con XALAN se produce un colapso del sistema, que lleva la CPU de las máquinas al 100% de uso y estoy hablando de equipos dimensionados para alcanzar cargas muy superiores, del orden de 10 ~ 20.000 usuarios concurrentes.
El diagnostico
Después de laboriosos estudios del entorno de producción y de muchas horas de "laboratorio" se logró reproducir la incidencia. Para ello , simulando al máximo posible la situación real, se realizaron de forma concurrente un gran número de transformaciones XSL, que a su vez hiciesen uso de otros includes XSL. Veamos el siguiente fragmento de código:
threadInfo.thread = (new Thread() { public void run() { try { xslt.doTransform(chooseRandomXSL(), xmlFileName, outFileName); } catch (IOException e) { e.printStackTrace(); } } }); threadInfo.thread.start();
Cuando el número de transformaciones XSLT es muy elevado (durante las pruebas de laboratorio a partir de un valor de 150), se produce una progresiva situación de colapso similar a la vista en el entorno de producción (ver siguientes imágenes).
Durante el estudio de esta situación se obtuvieron los siguientes datos:
- Los bloqueos se producen cuando coinciden transformaciones XSL que hacen uso un mismo fichero de include. En la primera de las dos imágenes mostradas se observa como los ficheros quedan abiertos de forma indefinida.
- En determinadas ocasiones (como se ve en la segunda de las imágenes) se sigue produciendo el bloqueo aun cuando todos los ficheros hayan ya cerrados.
- En los casos en los que la prueba llegó a finalizar (cuando el nivel concurrencia simulado no había alcanzado el umbral), a medida que este valor aumentaba, el tiempo empleado durante las transformaciones se volvía inaceptable.
- Esta situación sólo se produce si el documento XSL no ha sido compilado anteriormente. Si los Translets ya han sido generados de manera previa a la ejecución, la concurrencia de transformaciones simultáneas tiene por único límite la capacidad del equipo en el que se realiza: En laboratorio, y un equipo muy modesto en cuanto a prestaciones se refiere, se han logrado ejecutar más de 700 transformaciones de manera simultánea.
A continuación, con el objetivo de confirmar hasta qué punto el uso de includes es un factor determinante para que se produzcan las situaciones de bloqueo descritas, se realizó una versión de las plantillas XSL que no usasen includes pero que realizaran idéntica función.
El resultado de esta prueba fue que, si bien el número de compilaciones simultáneas debe ser mayor (fue necesario incrementar el valor hasta 400, frente a las 150 anteriores), el problema se acaba reproduciendo igualmente.
La conclusión
El compilador de XALAN tiene un grave problema de rendimiento cuando concurren múltiples transformaciones XSL que necesitan realizar la compilación de Translets. Esta situación se agrava aún más, cuando se hacen uso de includes en los documentos XSL.
La solución
Según se ha visto hasta el momento, para resolver las situaciones descritas existen varias soluciones posibles:
- Haciendo uso de las capacidades que XALAN proporciona, es factible compilar todas las XSL de manera previa a la ejecución de la aplicación.
- Si se limitan el número de compilaciones simultaneas que XALAN realiza, el problema también desaparece.
Si bien la opción primera soluciona el problema por sí sola, se ha optado por implantar la segunda acción y poder garantizar de esta manera una total escalabilidad y estabilidad del sistema.
Veamos a continuación un extracto de la solución aplicada:
private static HashMap templatesCache = new HashMap(); public Templates getTemplates(String xslFile) throws TransformerConfigurationException { Templates templates = null; // El acceso al HashMap no está sincronizado, esta región de exclusión // mutua garantiza el mejor rendimiento y continua siendo "thread safe" templates = (Templates) templatesCache.get(xslFile); synchronized (templatesCache) { if (templates == null) { templates = super.getTemplates(xslFile); templatesCache.put(xslFile, templates); } } return templates; }
Esta manera de gestionar los procesos de transformación XSL limita el número de compilaciones que el sistema realiza a la vez que garantiza un acceso inmediato la transformación XSL dado que la plantilla se carga en memoria una sola vez, las transformaciones se realizan de una forma mucho más eficiente.
Por el contrario, si bien se consideran mínimas en su impacto, hay que reseñar que este enfoque tiene dos "debilidades" principales:
- De igual manera a como se hace con las páginas JSP, el primer acceso que se haga a una plantilla XSL, será algo más lento (< 1 segundo) al ser necesario realizar el proceso de compilación.
- Para lograr una mayor eficiencia del sistema se cargan en memoria todas las transformaciones XSL a medida que se van usando.
Imprimir este artículo
Aún no hay trackbacks.






31 Enero, 2008 - 01:22
Me encanta el código fuente que has puesto de “getTemplates(String xslFile)”, sin duda hecho por la mano de un genio…
Un abrazo, monstruo!
31 Enero, 2008 - 02:53
Soy un mero aprendiz, me limité a copiar lo que otro hizo
…¡maestro!
15 Abril, 2008 - 23:22
La verdad que parece super . soy nuevo con java, con xsl y en el blog…intento reproducirlo y tengo serios problemas en mi conversión : consumo de procesador y lentitud.. tengo que intentar convertir a razon de 50.000 documentos por hora…se puede conceguir alguna ayuda en el blog ? Gracias amigos
15 Abril, 2008 - 23:42
Zamba, lo cierto es que el objetivo de 50.000 documentos hora es muy ambicioso: ¡¡¡¡14 transformaciones por segundo!!!
Para poderte ayudar necesitaría algún dato mas:
- Tamaño de los XML a transformar
- Tamaño de la XSL a usar
- ¿Se trata de un flujo constante de peticiones o por el contrario tienes picos de mas demanda?
Un saludo
15 Abril, 2008 - 23:48
Cmaj, primero y principal gracias por responderme, eres muy amable…te cuento estoy metido en un embrollo hace mas de 20 dias que estoy con esto y no puedo avanzar un apice….
primero intente compilar el xsl como dijistes y me tira el error (sundesasl sgcv10 dsgcedes) /sgcv10/software/OpenCM/server/Templates> java org.a
pache.xalan.xslt.Process -in 45484_4.0.xml -xsl 91.xsl -xsltc
(Location of error unknown)XSLT Error (java.lang.IllegalAccessError): class org.apache.xml.dtm.ref.sax2dtm.SAX2DTM2.AncestorIterator cannot access its superclas
s org.apache.xml.dtm.ref.DTMDefaultBaseIterators$InternalAxisIteratorBase
a continuacion intento incluir parte de tu codigo en lo que tengo, pero nada pasa….
la xsl a usar siempre es la misma y su tamaño es de 64 k y los xml varian 17-18 k ..
el flujo de peticiones es constante seria en un proceso tipo batch…
cualquier ayuda seria genial..mil gracias amigo
17 Abril, 2008 - 23:39
Curioso error
aunque supongo que tu estas hasta el gorro de él.
¿Existe la posibilidad de que hagas una pequeña prueba de concepto reproduciendo el error en el menor trozo de código posible y me la hagas llegar?
No te prometo nada, pero al menos lo intentaré. Envíamelo a xsltdoctor@gmail.com
Por cierto, no se si será relevante, pero ¿Que entorno usas? SO, JDK, versión Xalan, etc.
17 Abril, 2008 - 23:53
Por cierto, en la web de XALAN (http://xml.apache.org/xalan-j/faq.html) he encontrado este comentario:
jakarta-tomcat 4.1.* is packed with an old version of xercesImpl.jar. Based on the Endorsed Standards Override Mechanism, you should replace it with the newer xercesImpl.jar. You should add a newer xalan.jar and serializer.jar to Tomcat as well. Read the FAQ about Issues running Xalan-Java on JDK/JRE 1.4 or higher. Place the xalan.jar, serializer.jar, and xercesImpl.jar in the\common\endorsed directory, where is where the Tomcat application server is installed.
¿Es posible que te pase algo parecido, que tengas dos Xalan en el CLASSPATH?
Salu2