none
Liberar memoria RRS feed

  • Pregunta

  • Hola a todos.

     

    He realizado unas pruebas con una pequeña aplicación con formularios mdi, y con una serie de conexiones una base de datos sql server 2005.

     

    El caso es que he comprobado que la memoria que utiliza mi aplicación aumenta cada vez que abro una ventana (formulario) incluso si cierro un formulario y vuelvo a abrir el mismo la memoria se va a acumulando.

     

    En el evento FormClose de cada formulario he utilizado el método:

     me.Dispose()

     

    Pero no veo que se libere memoria.

     

    Muchas gracias por la ayuda.

     

    Javier.

     

    viernes, 20 de abril de 2007 12:59

Respuestas

  • Puedes intentar forzar la recogida del Garbage Collector, aunque no es muy recomendable...

     

    System.GC.Collect()

     

    Un saludo!

    lunes, 14 de mayo de 2007 10:00
    Moderador
  • No es recomendable en el sentido que según marca la teoría, los megas que comentas que están ocupados, en realidad no lo están, sino que están "cacheados" por el GC. Si el sistema realmente no dispusiera de memoria para otras tareas, la memoria sería liberada sin forzar el GC.

     

    No pasa nada si fuerzas, únicamente que Microsoft considera que sabrá escojer el momento mejor que nosotros...

     

    Un saludo!

     

    PD: Recuerda de marcar el hilo como contestado cuando consideres oportuno. Gracias!

    lunes, 14 de mayo de 2007 10:51
    Moderador

Todas las respuestas

  • .NET libera memoria mediante el Garbage Collector (GC) de forma automática con lo que no sería necesario ejecutar el Dispose que indicas. La forma de actuar de GC no tiene por qué ser tan lineal como esperas. Puede que se cierre el formulario pero que lo mantenga "cacheado" o simplemente no haga liberaciones parciales si todavía tiene recursos libres, algo que aunque pudiera ser contraproducente puede incrementar el rendimiento de la aplicación.

     

    La curiosidad que demuestras en tu consulta dice mucho a tu favor, pero no creo que debas preocuparte por este tema...

     

    Un saludo!

    viernes, 20 de abril de 2007 13:11
    Moderador
  • Gracias por la respuesta, me quedo algo más tranquilo.

     

    El caso es que la prueba la realizo con una pequeña aplicación, pero el caso es que estoy desarrollando otra con bastantes más formularios y controles de todo tipo, y viendo que cada vez que abro un formulario, por ejemplo form1, lo cierro, lo vuelvo a abrir y sigue aumentando la memoria, me he estado volviendo loco para ver como liberarla, porque además mi pc andaba justo de memoria, me he hartado de abrir internet explorer para superar mi límite pero seguía sin liberar.

     

    Gracias por la ayuda.

     

    Un saludo.

     

    Javier.

    viernes, 20 de abril de 2007 13:49
  • Quizás deberíamos entre todos darle un vistazo al siguiente artículo:

    http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/MTJ_2647.asp

     

    No he tenido tiempo, pero tratándose de Unai, seguro que nos resolverá muchas dudas...

     

     

    Un saludo!

    lunes, 23 de abril de 2007 10:10
    Moderador
  • Puedes utilizar CLR profiler para analizar mas a fondo donde se encuentra tu problema de memoria y ademas prueba a hacer alguna llamada al GC a ver si te libera memoria.

     

    Salu2,

     

    Colabora con el foro: Si la respuesta te es de utilidad marca la pregunta como respondida.

    Luis Ruiz Pavón

    MCP

    Blog: http://geeks.ms/blogs/lruiz

    lunes, 23 de abril de 2007 10:22
  • Hola a todos,

     

    Yo tengo el mismo problema. Mi aplicación es algo compleja, maneja bastantes formularios y multitud de conexiones contra SQL server 2000.

     

    La memoria aumenta de manera preocupante al abrir formularios dejando la aplicación KO tras varias aperturas/cierres del mismo formulario.

     

    Hemos forzado llamadas al GC.Collect() pero no obtenemos ninguna mejora.

     

    Se os ocurre algo más?

     

    Gracias por vuestra colaboración.

     

    Saludos

    DJ

    martes, 8 de mayo de 2007 18:08
  • No podeis centralizar todas las operaciones mediante una única conexión a SQL?

     

    Eso reduciria drásticamente los recursos necesarios.

     

    Un saludo!

    martes, 8 de mayo de 2007 22:14
    Moderador
  • Como bien dice Toni, para reutilizar el pool de conexiones de SQL Server se debe utilizar el mismo usuario para el connection string y no utilizar la autenticación windows integrada.

     

    Salu2

     

    Colabora con el foro: Si la respuesta te es de utilidad marca la pregunta como respondida.

    Luis Ruiz Pavón

    MCP

    Blog: http://geeks.ms/blogs/lruiz

    miércoles, 9 de mayo de 2007 7:18
  • Hola a todos.

     

    Cuando Toni y Luis se refieren a centralizar conexiones, os referís a crear una conexión global al principio, en lugar de crear una cada vez que sea necesario??

     

    Y otra duda más, en principio yo utilizaba autenticación mixta SQL Server, pero después de leer en varios foros y otros documento parecía claro que la recomendación más segura era la autenticación windows. Esto quiere decir que debemos elegir entre una aplicación que consuma menos recursos o una aplicación más segura.

     

    Gracias y un saludo.

    jueves, 10 de mayo de 2007 21:10
  • Por supuesto que es mas seguro utilizar la autenticación windows porque puedes personalizar mejor los permisos de SQL Server sobre tablas, prodcedures... que teniendo solo un usuario o 2 que suele hacerse un usuario para las select y otro para los insert, updates y deletes, pero claro estas penalizando mucho el pool de conexiones de SQL Server.

     

    Salu2

     

    Colabora con el foro: Si la respuesta te es de utilidad marca la pregunta como respondida.

    Luis Ruiz Pavón

    MCP

    Blog: http://geeks.ms/blogs/lruiz

    viernes, 11 de mayo de 2007 6:51
  • Buenas de nuevo,

     

    En cuanto a lo de la conexión global, pues sí, viene a ser eso, pero de forma algo elegante. Yo usaría el patrón de diseño Singleton para hacer accesible la conexión desde todos los "rincones" de tu aplicación. Si no coneces Singleton, te recomiendo que le dediques un rato al siguiente enlace:

     

    http://www.mug.org.ar/Patrones/ArticPatrones/304.aspx

     

    En cuanto al tema de la autentificación, yo no veo que un sistema de seguridad u otro, tenga grandes impactos en cuanto al rendimiento, sinceramente.

     

    Un saludo!

    viernes, 11 de mayo de 2007 6:51
    Moderador
  • Lo que también hay que tener en cuenta con un sistema de seguridad u otro es el tema de las licencias....
    viernes, 11 de mayo de 2007 7:01
    Moderador
  • Pues si Toni si tiene grandes impactos, en una aplicación concurrente dentro de una intranet con muchos usuarios, si utilizas autenticación windows en SQL Server estas creando un nuevo pool de conexion para cada usuario que realice una conexión con la base de datos y no reaprovehcas el pool que te brinda SQL Server si conectaras con un usuario sólo, por eso está el poner un uid con su password en la cadena de conexión o poner integrated security a true y te puedo asegurar que penaliza el rendiemiento de tu aplicación porque estas penalizando en el preformance de tu servidor de base datos

     

    Salu2

     

    Colabora con el foro: Si la respuesta te es de utilidad marca la pregunta como respondida.

    Luis Ruiz Pavón

    MCP

    Blog: http://geeks.ms/blogs/lruiz

    viernes, 11 de mayo de 2007 8:12
  • OK, tienes toda la razón. No me he explicado bien. Me refería a usar a un usuario windows genérico, por aquello de "mejorar" la seguridad. En todo caso, lo has expuesto magníficamente.

     

    Un saludo!

    viernes, 11 de mayo de 2007 8:24
    Moderador
  • Gracias Toni Wink

     

    Y ya aprovechando esto de las buenas practicas os dejo un enlace que os va a gustar:

     

    Performance Best Practices at a Glance

     

    Salu2

     

    Colabora con el foro: Si la respuesta te es de utilidad marca la pregunta como respondida.

    Luis Ruiz Pavón

    MCP

    Blog: http://geeks.ms/blogs/lruiz

    viernes, 11 de mayo de 2007 8:35
  • Pues qué Platero? te hemos ayudado o más bien te hemos mareado?

     

    Comentanos la jugada, que esto está animado!

     

     

    Saludos!

    viernes, 11 de mayo de 2007 15:43
    Moderador
  • Buenas a todos,

     

    Ahora mismo voy a ver como me las ingenio para crear esa conexión global de un modo "elegante" para probar en una pequeña aplicación los recursos que ahorra de ese modo, y de paso cambiaré la autenticación integrada de windows a la de SQL Server.

     

    Veremos que va saliendo, y que resultados obtengo, ya os contaré...

     

    Muchas gracias a todos.

     

    Javi.

     

    lunes, 14 de mayo de 2007 8:13
  • Buenas,

    He hecho la prueba de poner una conexión común global y compartida.

     

    Code Snippet

    Imports System.Data.SqlClient

    Public Class Accesos

    Public Shared objConexion As SqlConnection = New SqlConnection

     

    Public Shared Sub crear_Conexion()

        Dim strConexion As String = My.Settings.AgendaConnectionString

        Accesos.objConexion.ConnectionString = strConexion

    End Sub

    Public Shared Sub abrirConexion()

        objConexion.Open()

    End Sub

    Public Shared Sub cerrarConexion()

        objConexion.Close()

        objConexion.Dispose()

    End Sub

    Private ReadOnly Property getConexion() As SqlConnection

       Get

         Return objConexion

       End Get

    End Property

    End Class

     

    Lo que hago es abrir la conexión al cargar el primer formulario, y cerrarla al cerrar la aplicación. Seguramente no sea un método muy elegante.

    Para utilizar la conexión simplemente llamo Accesos.objConexion

     

    Y al cerrar cada formulario sigo colocando en el evento FormClosed

         Me.Dispose()

     

    Para que tengáis una idea de los recursos que estoy manejando en la aplicación de prueba:

     

    Nada más introducir los credenciales y abrir el formulario principal - > 31 Megas.

     

    Con todos los formularios abiertos (unos 8 con DataSet, Listados...) - > 58 Megas.

     

    Una vez abiertos todos los formularios, cierro todos y se queda en - > 56,5 Megas.

     

    Ahora entenderéis mi preocupación....

     

    Os dejo el siguiente enlace de Jorge Serrano:

    http://geeks.ms/blogs/jorge/pages/visual-basic-2005-instanciando-formularios.aspx

     

    Un saludo.

     

    Javi.

     

     

     

    lunes, 14 de mayo de 2007 9:37
  • Puedes intentar forzar la recogida del Garbage Collector, aunque no es muy recomendable...

     

    System.GC.Collect()

     

    Un saludo!

    lunes, 14 de mayo de 2007 10:00
    Moderador
  • Hola,

     

    Bueno Toni, parece funcionar y recupera recursos con

    System.GC.Collect()

     

    Pero no me asustes!!! ¿Porqué no es recomendable?

     

    Lo extraño es que me suceda esto, y que no haya más quejas de recursos por parte de más desarrolladores. Yo creo que no hago nada raro para que sólo me suceda a mi....

     

    Gracias!!!!

     

    Javi.

    lunes, 14 de mayo de 2007 10:35
  • No es recomendable en el sentido que según marca la teoría, los megas que comentas que están ocupados, en realidad no lo están, sino que están "cacheados" por el GC. Si el sistema realmente no dispusiera de memoria para otras tareas, la memoria sería liberada sin forzar el GC.

     

    No pasa nada si fuerzas, únicamente que Microsoft considera que sabrá escojer el momento mejor que nosotros...

     

    Un saludo!

     

    PD: Recuerda de marcar el hilo como contestado cuando consideres oportuno. Gracias!

    lunes, 14 de mayo de 2007 10:51
    Moderador
  • Gracias Toni, me dejas más tranquilo.

     

    Para intentar forzar a Windows a que utilice esa memoria, decidí abrir programas hasta superar con creces el uso de mi RAM, pero nada, mi pequeña aplicación se hacía fuerte, y seguía acumulando recursos.

     

    Gracias de nuevo.

     

    Javi.

    lunes, 14 de mayo de 2007 10:54
  • Buenas tardes, me encuentro con el mismo problema. La aplicación empieza a consumir memoria y no la libera aunque finalice el formulario.

    En primera instancia forcé la liberación de memoria en el OnIdle de la  aplicación, cosa que funcionaba razonablemente bien. Pero encontré en una página web la llamda al API

    SetProcessWorkingSetSize, que realmente libera memoria. De momento estoy investigando el funcionamiento de este API y sus consecuencias.

     

     

    miércoles, 3 de diciembre de 2008 16:02
  • recuerde que el tema de que el collector grabable queden la memoria ocupada, es que asi las cachea.
    Si tu aplicacion utiliza varios servicios o varios dataset, o n formulario, imaginate que el netframework entre CLR y el GC analizan el lo solicitado y en caso que eso ya este porcesado lo levanta desde el cache.

    Si vos forzas la limpieza del GC puede pasar,  liberas memoria, pero vas a necesitar mayor capacidad de procesamiento ya que nunca lo vas a estar levantando de cache siempre lo vas ha estar generando.

    A mi creer es mejor que te ocupe el GC memoria . Estaria bueno hacer la siguiente prueba un bucle infinito donde te vayas ocupando la memoria de GC. Si la teoria de microsoft es correcta solo el GC se va a ir limpiando sin colgarse la aplicacion.
    viernes, 6 de febrero de 2009 13:06