Markus Kohler ha publicado en su blog el resultado de un análisis del consumo de memoria de Eclipse usando la herramienta Eclipse Memory Analyzer (MAT) de la cual es comitter. Esta herramienta es un plugin que analiza los heap dumps generados por la JVM, en específico aquellos con el formato HPROF. Formato soportado por la JVM de Sun, de HP y SAP (no se menciona si BEA JRockit lo soporta).
El análisis se realizó usando la JDK 1.6_10 y Eclipse 3.4 M7 con el proyecto de Winstone cargado. Los resultados son muy interesantes. Como podrás ver en el post de Markus en el resumen del análisis se aprecia que el corrector ortográfico es el objeto que ocupa más memoria memoria del IDE: 5,6 Mbyte lo que equivale a casi el 25% del total de 22,7 Mbytes ocupados por Eclipse. Este corrector ortográfico se incluye desde Eclipse 3.3 (Europa) y para mi es una de las características más molestas del IDE: sólo tiene soporte para Inglés y lo último que necesito es que mi IDE me diga si escribí bien o mal un comentario y además me lo marqué en rojo. Además de que siempre está activado por defecto.
La siguiente sorpresa viene cuando Markus decidió ver porqué esta herramienta ocupa tanta memoria y la respuesta es toda una sorpresa: el corrector está implementado como un enorme HashMap que hace un map de un String a una lista de Strings. Markus planea poner un bug sobre este tema, esperemos que lo hayan arreglado para cuando Eclipse 3.4 sea publicado.
El segundo punto que revisa es lo que llama su truco favorito para análisis de consumo de memoria: buscar Strings duplicados. Eclipse MAT tiene una herramienta que le ayudó en este trabajo y con la cual pudo detectar que los objetos String ocupan 12Mbytes del total de 22,7; de esos 4 son ocupados por el corrector ortográfico. Al hacer unh group by de los Strings, Markus pudo detectar los duplicados que muestran que Strings como "id" están duplicados 1988 veces o "name" 1210. El siguiente paso fue ver que clases eran la responsables de estas duplicaciones y encontró que ConfigurationElement es la clase responsable por mucho de la mayor cantidad con 13242.
Como dice Markus, que existan tantos Strings duplicados en una aplicación es el mayor problema de desempeño presente en la mayoría de las aplicaciones Java, esta herramienta nos permite detectarlo e incluso nos determina las clases responsables.
En mi experiencia este tipo de análisis en el mejor de los casos sólo se hacen cuando las cosas empiezan a fallar con típicos OutOfMemory y una vez que el desarrollo ha terminado. Markus nos demuestra en este artículo como de una forma bastante sencilla fue posible detectar dos objetos que consumen una cantidad de memoria importante (la implementación del corrector ortográfico y los Strings duplicados de la clase ConfigurationElement) que de arreglarse tendrían un impacto bastante bueno en el consumo de memoria de Eclipse. Con este tipo de herramientas ya no hay excusas para dejar estos análisis hasta que los errores empiecen a surgir.
Por cierto, Markus tiene planeado realizar el mismo análisis de Netbeans así que no está de más revisar su blog para cuando lo publique.
Sólo quiero comentar alguna cosilla: para mi un memory leak no es que haya mucha memoria ocupada, sino que la memoria vaya creciendo de alguna manera indefinidamente y no pueda ser liberada. Que haya Strings duplicados es una mala idea, pero no hace que la memoria vaya creciendo indefinidamente.
Le echaremos un vistazo a la herramienta, para compararla con el profiler de Netbeans (que me ha sacado de más de un apuro)
Salu2
No entiendo lo de los Strings duplicados. La JVM no tiene un pool de Strings precisamente para evitar tener el mismo String duplicado?
Como se puede desabilitar el corrector ortográfico¿?
Eso digo yo como se desabilia el corrector.
para deshabilitar el corrector en 3.3: Window -> Preferences -> General -> Editors -> Text Editors -> Spelling
no estoy seguro sin 3.4 es la misma opción
sí, existe un pool pero se puede forzar la creación de un nuevo objeto String aun existiendo previamente en el pool
Yo sé que con esto de las metodologías ágiles, como XP por ejemplo, hay que documentar lo suficiente el código, ya que es una de las pocas documentaciones que van a quedar.
Ahora, ¿habrá algún programador en la Tierra que desee un corrector ortográfico en un IDE de programación?
Estoy de acuerdo con ibon en que esos problemas de consumo de memoria no son "memory leaks", se trata simplemente de que la aplicación consume mucha memoria por como esta diseñada, ¿que se podría diseñar para que consuma menos?, pues seguramente, por ejemplo no teniendo el diccionario entero en memoria y implementado alguna cache, es la batalla de siempre entre el consumo de memoria y el rendimiento, la virtud esta en el termino medio que dicen por ahí.
Con lo que no estoy de acuerdo con ibon es con su definición de memory leak xd, un ML es una zona de memoria reservada y que la aplicación ya no necesita/utiliza. Es importante esta diferencia entre "no utiliza" y "no puede liberar", en java siempre puedes liberar por que el GC se encarga de borrar la zona de memoria cuando nadie la referencia, pero puedes tener memory leaks porque mantienes referencias a cosas que realmente ya no necesitas. En C++ por ejemplo si puedes "no poder liberar" porque reservas una zona de memoria y luego pierdes su referencia, y ya no puedes liberarla porque has perdido la información de donde esta esa zona reservada y no puedes hacer "delete".
Exacto remoh... pensaba solo en Java, y con "no poder liberar", me refería al GC, que aunque ya no hacemos uso de esos objetos no puede liberarlos debido a que seguimos manteniendo las referencias.
Salu2
Espero no salirme mucho del tema, pero es que optimizar es alguna de mis debilidades (claro está sin llegar a extremos)
"La siguiente sorpresa viene cuando Markus decidió ver porqué esta herramienta ocupa tanta memoria y la respuesta es toda una sorpresa: el corrector está implementado como un enorme HashMap que hace un map de un String a una lista de Strings. Markus planea poner un bug sobre este tema, esperemos que lo hayan arreglado para cuando Eclipse 3.4 sea publicado."
Tengo una duda existencial: ¿Implementar un enorme HashMap es contraproducente? Que alternativas podría tener. Cuando yo recupero registros de la Base de Datos, generalmente prefiero volcarlas sobre un HashMap en vez de un Bean puesto que mi tabla puede cambiar y eso obligaría cambiar mi Bean ¿Cuál es la forma coherente para trabajar? ¿Es verdad que un HashMap es más rapido que un HashTable? Muchas preguntas y tengo más que me gustaría formular pero espero no molestarlos.
Saludos
Raúl
Yo estoy mas con Ibon en cuanto a que solo lo considero Memory Leak si no la puede liberar el GC. Si hemos de considerar ML cualquier memoria que no usemos aunque el GC la pueda liberar, entonces todos los programas tienen ML constantemente, ya que como no liberamos la memoria explicitamente...
Bueno discusiones semanticas aparte, no esta nada mal que se corran estos programas de diagnostico sobre los productos populares y se analicen estas cosas, si cosas parecidas se hicieran sobre muchas librerias populares que la gente tiene en un pedestal, muchas sorpresas se llevarian algunos :).
La pregunta sería... si desactivas el corrector, deja de ocupar memoria o simplemente deja de actuar?
S!
Markus ha contestado a varios comentarios de este post, a pesar no hablar español el traductor de google le sirvió para darse una idea de lo aquí discutido. Su respuesta se puede leer en: http://kohlerm.blogspot.com/2008/05/eclipse-memory-leaks.html
Como ya me habían corregido Greeneyed, Remoh e Ibon; los problemas discutidos por Markus no se tratan de memory leaks. El autor enlaza a un post de Andreas Buchen (otro commiter de Eclipse MAT) donde habla sobre como usar la herramienta para encontrar leaks: http://dev.eclipse.org/blogs/memoryanalyzer/2008/04/21/immortal-objects-or-how-to-find-memory-leaks/
Por otro lado, contestando a Greeneyed, el deshabilitar el corrector ortográfico parece que sí funciona para liberar memoria y añade un link al bug que levantó sobre el asunto: https://bugs.eclipse.org/bugs/show_bug.cgi?id=233156.
Estupendo. El mundo Open Source en funcionamiento para ir avanzando :).
(Me puedo equivocar, de hecho, seguro que mi conocimiento esta obsoleto).
@Raul: Respecto al HashMap: mirar weak y soft references , mirar info sobre (mem)cachés también. Básicamente te puedes crear un hash de tamaño máximo limitado e ir "reciclando" entradas segun algún algoritmo de "envejecimiento".
Respecto a Strings:
Literal strings within the same class (§8) in the same package (§7) represent references to the same String object (§4.3.1).
JB , puede que todo esto sea una tontería ... digo malentendido
PD: Un pool hecho "a manubrio" en Eclipse:
http://www.koders.com/java/fidE5DFACAD2BFCA3F985DDCC3DAB10E40DAA769D0B.aspx?s=file%3Asemap*.java
@greeneyed: Si cosas parecidas se hicieran sobre muchas librerias populares que la gente tiene en un pedestal, muchas sorpresas se llevarian algunos :).
Si pero, hoy le tocaba al "maravilloso" Eclipse ;) (NetBeans tendrá sus cosas (supongo) :P )
Aunque lo de la librería es grave, más grave me parece que pase en el código desarrollado para un cliente (que ese se paga) y allí seguro que hay más.
Y si estas cosas pasan en Java, en otros lenguajes de los que no me quiero acordar ... Heroes of Might and Magick ... Parche número ....
Para que el GC funcione hay que usar x = null de vez en cuando, que parece que a algunos se le olvida. En Swing con tanto listener y tan poco estilo funcional es relativamente facil dejar objetos auxiliares que ya no se usan accesibles. Me parece una lección interesante para los que piensan que la programación en el servidor es más seria y dificil que la programación en el cliente. En el servidor estas cosas se suelen testear; el cliente, como es un pc de 300 € ... Y no hablemos de leaks en el navegador :)
Los 4 últimos mensajes, (contando con este) son mios (JB).
Me ha gustado ver la rapidez con la que se citaban de unos entradas en otras :)
Aunque lo de la librería es grave, más grave me parece que pase en el código desarrollado para un cliente (que ese se paga) y allí seguro que hay más.
Si, pero lo que ocurre es que muchas librerias "comunes", hint hint, que se usan en desarrollos tienen problemas que no se ven a simple vista, pero como echando mas hardware y reiniciando de vez en cuando se arregla...
Para que el GC funcione hay que usar x = null de vez en cuando,
No es cierto. Eso en "algunos casos" puede ahorrarle al GC alguna vuelta en el agoritmo de deteccion de referencias huerfanas, pero eso de que si no lo pones el GC no puede liberar el objeto, es un mito. El GC es mucho mas listo que eso.
Escribe tu comentario