Solucionando un memory leak en Genexus 9.0/ Generador .NET
Una aplicación GeneXus 9.0 generada en C#, estaba teniendo problemas de performance. Es normal que la aplicacion este funcionando por semanas en forma ininterrumpida, procesando miles de mensajes por dia.
Es una aplicación un poco atípica, pues funciona como demonio y lo que hace es procesar mensajes XML,los procesa y devuelve mensajes en XML.
La lógica del procesamiento batch utiliza unas 200 tablas de la base de datos, para poder hacer validaciones y grabar las entidades generadas por los mensajes.
El programa empezaba funcionando correctamente (o sea rápido) pero con el correr de los días, se ponía mucho mas lento. A partir del cuarto dia, la performance era muy mala. Si se bajaban todas las instancias del programa (habitualmente hay 10) y se volvían a subir, la performance era buena nuevamente.
Ademas, el problema no podía estar en la base de datos, pues el resto de la aplicación funcionaba correctamente cuando esta aplicación se ponía muy lenta.
Los principales sospechosos fueron los SDT que son usados en forma intensiva en los programas. Buscamos donde se podía estar quedando colgado algún SDT sin destruir pero no encontramos nada.
También se abrían varios archivos XML del file system, pero todos eran cerrados correctamente.
Luego de varias horas de profiling con herramientas de .NET, vimos que si bien el proceso consumía memoria, la misma era liberada correctamente con la corrida del Garbage collector de .NET.
Las gráficas de consumo de memoria a traves del tiempo aumentaban pero muy lentamente... El consumo de memoria luego de varios días, era superior pero no extremadamente alto.
Decidimos habilitar el log en el archivo de configuración de la aplicación (el log4net de web.config), de forma de ver donde se estaban produciendo las demoras cuando la aplicación se ponía lenta.
Las sentencias en la base se ejecutaban en forma rápida, pero demoraba mucho entre una sentencia y otra.
El lugar donde se producía la demora, era en las rutinas internas de GeneXus (Gxclasses.dll) lo que era el peor lugar para que sucediera, pues de las cuales no teníamos los fuentes por lo que solo podíamos intentar adivinar que era lo que estaba pasando.
Aumentamos la cantidad de cursores abiertos que se tenían en la aplicación, pasando de 100 a 200 pero igual con esto seguimos teniendo el problema.
Luego de varias idas y vueltas, probamos desconectarnos utilizando el DBConnection y volver a conectarnos a la base de datos, de forma de vaciar todo el pool de conexiones con el código:
&DBConnection.disconnect()
&DBConnection.Connect()
Bazzinga!!. Con este sencillo código logramos solucionar el problema. Agrego unos 4 segundos adicionales al procesamiento de cada mensaje, pero logro hacer mucho mas estable la aplicación. Después de haber agregado dicho código, no volvimos a tener reportes de lentitud en el proceso.
Fue un error que nos tuvo entretenidos a unos cuantos y nos permitió aprender muchas cosas. Lo reportamos a Artech y esperemos que quede solucionado en versiones posteriores.
Es una aplicación un poco atípica, pues funciona como demonio y lo que hace es procesar mensajes XML,los procesa y devuelve mensajes en XML.
La lógica del procesamiento batch utiliza unas 200 tablas de la base de datos, para poder hacer validaciones y grabar las entidades generadas por los mensajes.
El programa empezaba funcionando correctamente (o sea rápido) pero con el correr de los días, se ponía mucho mas lento. A partir del cuarto dia, la performance era muy mala. Si se bajaban todas las instancias del programa (habitualmente hay 10) y se volvían a subir, la performance era buena nuevamente.
Ademas, el problema no podía estar en la base de datos, pues el resto de la aplicación funcionaba correctamente cuando esta aplicación se ponía muy lenta.
Los principales sospechosos fueron los SDT que son usados en forma intensiva en los programas. Buscamos donde se podía estar quedando colgado algún SDT sin destruir pero no encontramos nada.
También se abrían varios archivos XML del file system, pero todos eran cerrados correctamente.
Luego de varias horas de profiling con herramientas de .NET, vimos que si bien el proceso consumía memoria, la misma era liberada correctamente con la corrida del Garbage collector de .NET.
Las gráficas de consumo de memoria a traves del tiempo aumentaban pero muy lentamente... El consumo de memoria luego de varios días, era superior pero no extremadamente alto.
Decidimos habilitar el log en el archivo de configuración de la aplicación (el log4net de web.config), de forma de ver donde se estaban produciendo las demoras cuando la aplicación se ponía lenta.
Las sentencias en la base se ejecutaban en forma rápida, pero demoraba mucho entre una sentencia y otra.
El lugar donde se producía la demora, era en las rutinas internas de GeneXus (Gxclasses.dll) lo que era el peor lugar para que sucediera, pues de las cuales no teníamos los fuentes por lo que solo podíamos intentar adivinar que era lo que estaba pasando.
Aumentamos la cantidad de cursores abiertos que se tenían en la aplicación, pasando de 100 a 200 pero igual con esto seguimos teniendo el problema.
Luego de varias idas y vueltas, probamos desconectarnos utilizando el DBConnection y volver a conectarnos a la base de datos, de forma de vaciar todo el pool de conexiones con el código:
&DBConnection.disconnect()
&DBConnection.Connect()
Bazzinga!!. Con este sencillo código logramos solucionar el problema. Agrego unos 4 segundos adicionales al procesamiento de cada mensaje, pero logro hacer mucho mas estable la aplicación. Después de haber agregado dicho código, no volvimos a tener reportes de lentitud en el proceso.
Fue un error que nos tuvo entretenidos a unos cuantos y nos permitió aprender muchas cosas. Lo reportamos a Artech y esperemos que quede solucionado en versiones posteriores.
Muy bueno el post! Tengo una pregunta cuando decis "funcionaba como un demonio", se ejecutaba cada N minutos o como era? porque si fuese cada N minutos el se deberia conectar en cada vez que se ejecutaba y desconectar cuando terminaba.
ResponderBorrarTe felicito por el post!
Fabricio:
ResponderBorrarEl programa queda funcionando en forma continua, las 24 horas del dia en un loop infinito.
En realidad, son 10 procesos identicos, que estan esperando mensajes. Cuando llega un mensaje, es procesado por uno de estos y lo responde.
Existen mecanismos para bajar todos los procesos en forma ordenada.
Gracias por tu comentario.
En realidad el problema sigue estando ahí, solamente encontraste una forma de "escape".
ResponderBorrarDe todas formas, el Workaround te está dando una posible pista de por donde investigar (para que sea corregido en el runtime)
excelente.... pero... funcionara con una app 3 capas?, tengo una app que est amuy lenta en las consultas y las grillas cargan registro a registro lentisimo...
ResponderBorrarAnonimo:
BorrarSi el problema de la lentitud con tres capas, empieza luego de varias horas que la aplicacion esta funcionando, podria ser.
Al empezar la aplicacion ya esta lenta?
Hola, tengo GX 9 corriendo en Windows 2003 terminal services ya que hay varios desarrolladores, el compilador anda lentisimo para generar, alguien tiene algun pique
ResponderBorrarEn que estas generando?
BorrarHemos tenido problemas de lentitud generando y compilando java, cuando varias personas acceden a la misma KB.
Hola,
ResponderBorrarGx 9.0 con dbms iseries native y con generador .net
En ejecucion de los usuarios da de repente lo siguiente en el operation navigator
Cursor C000086 no abierto
Cursor C000056 no abierto
Cursor C000045 no abierto
Cursor C000038 no abierto
.........................
¿por que pueda dar y como solucionarlo?
Gracias
Estoy en Genexus Ev 1 generando a C# pero la aplicacion ahora esta lenta, al principio estaba rapido ya llevo tres meses en producccion y se me pone lenta con internet inalambrico..Que podra ser?..
ResponderBorrarPrimero, revisaria el tuning en la base de datos.
BorrarSiempre empiezo a revisar la base de datos, y las sentencias lentas, cuando una aplicacion estaba funcionando rapido y con el paso del tiempo, se pone lenta.
si ya hicimos un tuning en la base de datos, los store procedure funcionan bastante bien, la base de datos esta estable, lo que me parece demasiado lento, es la forma en que responde a los menus, botones, carga de combos.
ResponderBorraresto solo lo hace en redes inalambricas, en mi oficina funciona bastante bien, en mis fincas tengo el problema que estoy via satelital.
Ya revise la base de datos y sigue lento, ahora otra pregunta?. Como hago para pasar actualizacion solo un web panel y no toda la aplicacion de genexus a IIS.. que actualmente traslado todo el directorio Web, hay una forma de hacerlo mas simple y no sacar a todos los usuarios
ResponderBorrarSi ya se realizo una instalacion y no se cambio de version del generador, alcanza con copiar la DLL con el mismo nombre del objeto (que esta en el directorio bin) y el javascript que esta en directorio del modelo que tiene el mismo nombre del objeto.
BorrarTambien puede necesitarse copiar las dll de uso general como genexus.artech.gxcommon.dll. Deberias ordenar por fecha las dll y copiar las ultimas generadas.
Existe una extension que se llama CSharpDeployment (la podes buscar en http://marketplace.genexus.com/ ) que hace mas facil la instalacion.
Muchas gracias me has sacado ya de un monton de apuros que estoy teniendo con genexus ev1. la lentitud no se con que mas probar, lo de la actualizacion ya me jalo, muchas gracias. Alguna propiedad del modelo, o alguna propiedad en el server fijate que tengo windows server 2003 con IIS pero si la velocidad de carga en botones, combos es mi mas serio problema lo raro es que es con red inalabrinca.
ResponderBorrarEn algunos casos que tuvimos que ejecutar aplicaciones WEB con lineas de mala calidad, lo que hicimos fue minimizar al minimo el HTML generado.
BorrarPor ejemplo, achicando el CSS (Theme), mostrando pocos registros, sacandole todo seteo de colores, que la font sea el mismo en toda la aplicacion y se setee en el theme y no en el html, etc.
Tambien conviene revisar el trafico en ajax que pueda tenerse. En algunos casos puede convenirte cambiar los combobox y dynamic combos por campos edit.
Gracias, kabal eso estamos haciendo, colocando listas de seleccion en vez de combobox donde miramos que se tarda mucho en cargar las paginas. EStamos utilizando el thema de Genexus en nuestra aplicacion. Fijate que prove desde otra maquina actualizar la pagina, solo copiando un reporte, su dll y su js. y si me jalo el reporte pero sin datos, ahora si lo hago desde mi maquina nitido. Que me haría falta copiar?. Muchas gracias por tu apoyo
ResponderBorrarpara el reporte copie el .cs y el .rsp no se si hace falta copiar otro el .js no lo encontre.
ResponderBorrarEnrique, tus aportes al conocimiento genexus es invaluable, Yo estoy intentando convencer a mi gente de ubicar a esta como la herramienta de desarrollo, pero justo cuando trato de demostrar su validéz, me apareció un problema y que no logro solucionarlo y me animé a escribirte, dada tu amplia experiencia. No se donde mas colocar este tema. Estamos probando con Genexus 9, .NET ,web, postgresql, y windows server 2008, con IIS7. Estaba demostrando toda la versatilidad de la herramienta, pero me aparece un limite en la aplicación web ya funcionando, del numero de registros que puedo insertar en una TRN de 2 niveles, máximo 10 registros en unos casos y 26 en otros, todo funciona casi perfecto, y solo por este tema, no me permiten presentar una buena evaluación.
ResponderBorrarAnonimo:
BorrarPorque decis que tiene un limite maximo de 10 registros en las transacciones?
No tenes la opcion de Add Lines?
Se puede definir que las grillas tenga las cantidad de lineas que quieras inicialmente y ademas tenes la posibilidad de agregar lineas.
Podes leer en http://wiki.gxtechnical.com/commwiki/servlet/hwiki?RowsProperty,
Saludos.
Hola Enrique, Soy Manolo, gracias por tu atenta respuesta, sigo expresandote mi problema, si tengo 25 seteado en Rows, y se abren esas lineas en blanco para ingresar información, pero cuando ingreso una extra (la onceava), no la graba. Debo estar con algún problema, pero no se como detectarlo. Parecería que le falta memoria en el navegador del cliente? parecería que lo vuelve todo a cero...
BorrarGracias por tu pronta respuesta Enrique, Si tengo configurado en 25 el parametro rows, mi investigación está yendo a algun tipo de incompatibilidad con tal vez, Windows Server 2008, y el IIS7 o algo sobre memoria asignada al navegador del cliente, lo quisiera tu guia es como puedo levantar LOGS de rastreo para determinar don de esta mi problema, gracias por tu tiempo.
Borrar