30 noviembre 2005
Liberar Memoria Con Vb .NET
Chequeando una aplicación que estoy desarrollando, he verificado el uso excesivo de memoria que consumen las aplicaciones desarrolladas en NET FrameWork.
Despues de probar que descargaba correctamente todos los objetos que utiliza la aplicación mediante el uso del Dispose() y especificamentes los objetos DataSet y DataTable, ya que estos hay que descargarlos de memoria manualmente, observe que la memoria seguia sin descargarse correctamente. Por lo que probe con el GC (Garbage Collector) para forzar la liberación de memoria, pero el resultado fue identico.
Despues de probar, recompilar, optimizar el código fuente opte por «obligar» a la aplicación (al proceso) por completo a liberar la memoria no necesaria. Para ello me enfunde en el manejo de las Api’s, localizando SetProcessWorkingSetSize, que fuerza al proceso dado a liberar la memoria no usada (como cuando minimizas la aplicacion). Para ello me desarrolle la funcion ClearMemory, accesible desde cualquier punto de la aplicación que me permite optimizar el uso de memoria por parte del NET FrameWork.
‘Declaración de la API
Private Declare Auto Function SetProcessWorkingSetSize Lib «kernel32.dll» (ByVal procHandle As IntPtr, ByVal min As Int32, ByVal max As Int32) As Boolean‘Funcion de liberacion de memoria
Public Sub ClearMemory()Try
Dim Mem As Process
Mem = Process.GetCurrentProcess() SetProcessWorkingSetSize(Mem.Handle, -1, -1)Catch ex As Exception
‘Control de errores
End TryEnd Sub
eduardo said,
24 abril 2006 a 11:00 pm
hola maigo me parec eun execelente ejercicio, pero me gustaria saber si me puede explicar con mazanitas el SetProcessWorkingSetSize ya que lo que he encontrado en la web no me ayuda y que funcion tiene con el GC muchas gracias de ante mano
Delo said,
18 octubre 2006 a 8:06 am
Acojonante …
jose said,
19 febrero 2007 a 7:24 pm
MUY BUEN POST muchas gracias el unico problema es ke no los Gurus de .net no lo recomiendan ..
pero excelente..
cajina said,
7 junio 2007 a 9:39 pm
Me podrias explicar como usarlo y cuando?.
Es que estoy tratando de liberar punteros de una lista, recorriendo la lista hasta el final usando un procedimiento recursivo y tratando de liberar la memoria desde el ultimo hasta el primer puntero.
Pero no he podido asi que hasta el momento lo que he hecho es asignar Nothing a cada uno de lo punteros y limpiarlos.
cajina said,
7 junio 2007 a 9:40 pm
Y no se exactamente como trabaja ese procedimiento…
Jijijijiji
Gracias…
Alfonso May said,
12 julio 2007 a 5:43 pm
Excelente…
tina said,
20 agosto 2007 a 6:45 pm
Una función fantàstica.
Empezaba a volverme loca intentando reducir la memoria de mi programa, poniendo el colector en todos sitios sin conseguir nada, hasta que encontrado tu funcion.
Gracias por compartir tan esplendida función.
Jorge said,
23 agosto 2007 a 3:19 pm
Con SetProcessWorkingSetSize lo q haces es descargar toda la memoria al archivo de intercambio, luego a partir de ahí se supone q windows solo recupere la parte q necesita. Esto lo puedes ver facilmente con el task manager si escoges ver la columna VM Size para tu proceso.
Si alguien tiene un arreglo de punteros de codigo no administrado antes yo trataria de recorrer el arreglo, desbloquear la memoria de cada uno y liberarla de la misma manera q quizas la reservo con GlobalLock. O sea, usando APIs q con VB como el ejemplo seria algo así:
If _mypptr IntPtr.Zero Then
GlobalUnlock(_mypptr )
GlobalFree(_mypptr )
End If
_
Friend Function GlobalLock(ByVal handle As IntPtr) As IntPtr
End Function
_
Friend Function GlobalUnlock(ByVal handle As IntPtr) As Boolean
End Function
_
Friend Function GlobalFree(ByVal handle As IntPtr) As IntPtr
End Function
_
Friend Function GlobalAlloc(ByVal flags As Integer, ByVal size As Integer) As IntPtr
End Function
_
Private Function SetProcessWorkingSetSize(ByVal process As IntPtr, _
ByVal minimumWorkingSetSize As Integer, _
ByVal maximumWorkingSetSize As Integer) As Integer
End Function
Jorge said,
23 agosto 2007 a 3:35 pm
Otra cosa q olvide es con credenciales de adm no tendras problemas pero si el usr q ejecuta tu app no tiene el privilegio adecuado (PROCESS_SET_QUOTA) (La seguridad de Windows incluye la gestión privilegios sobre procesos)
no podras invocar la funcion SetProcessWorkingSetSize y es posible q ocurran algunas cositas en dependencia del servipack, version, configuracion, etc del equipo como q se audite en el Identificador de sucesos de windows, cierre de la app, etc. EJEMPLO EN http://support.microsoft.com/kb/831905/en-us…
Tambien esto solo funciona sobre WIn32 asi q es valido verificar la plataforma:
If (Environment.OSVersion.Platform = PlatformID.Win32NT) Then
Dim Mem As Process = Process.GetCurrentProcess()
SetProcessWorkingSetSize(Mem.Handle, -1, -1)
End If
Perriko said,
28 septiembre 2007 a 9:04 am
Va tan fino, que uno no se lo puede creer.
Tengo que matizar algo sobre lo que he leido.
VB si que libera la memoria cuando llamais a dispose y a GC, se marca como libre, pero se deja asignada al proceso, para reutilizarla en posteriores solicitudes (y como ya sabeis suelen ser muy posteriores), con esta llamada se obliga a reducir el tamaño de la memoria global asignada a la que realmente está utilizando el proceso:
En mi caso: he pasado de 110 megas a 8 Megas, lo gracioso es que ahora el monitor de memoria parece una montaña rusa.
fishertrout said,
26 febrero 2008 a 5:02 pm
Impresionante!!!! Los problemas que tengo de memoria al trabajar todos los usuarios en Terminal Server!!!!!!!! Ahora me falta provar que funcione.
La aplicación me comía mucha memoia del servidor.
90 Mb x 20 usuarios = 1,8Gb !!!!!!!!!!!!!!!!!!!!!!!
Si todo va bien…..
15 Mb x 20 usuarios = 0,3Gb
Mejoria, no……..
Buen trabajo.
fishertrout said,
26 febrero 2008 a 5:05 pm
Para quien lo necesite, también funciona en terminal server. Lo digo por tema de permisos y esas cosas.
fuuuuaaaaaaaaaaaaaa!!!!!
eric arturo said,
6 marzo 2008 a 7:33 am
Excelente aplicacion,habia creado controles dinamicos ,toda iba bien
lo unico era la enorme cantidad de recursos que consumia ahora cuando ejecuto todo solo me pasa de 3 a 2 genial FUNCION
GRACIASSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS
LINCHIS said,
14 marzo 2008 a 3:49 pm
Muchas gracias! me ha venido de lujo! 😉
Marco Esparza said,
23 julio 2008 a 6:11 pm
Mis felicitaciones es una exelente funcion, la neta morro que pesado estas .
GRACIAS Y MUCHO EXITO.
Marcos Garcia said,
25 septiembre 2008 a 3:50 am
Muchas gracias por publicar esta post , la verdad que fue de mucha ayuda pero una pregunta adicional , para que esto corra tambien desde una aplicacion web que deberia considerar?
Carlos Aristegui said,
3 febrero 2009 a 5:30 pm
O.O! increible! de 200.000 KB que consumia mi aplicación baja a 2.000 KB! es la hostia esto, ya no me tengo q preocupar del mal uso que hago de la memoria XD. Muchas gracias por el aporte!
Quique said,
20 abril 2009 a 6:58 pm
EXCELENTE LOCO!!! Le salvaste la vida a varias personas!
Giovanni Cedeño Prendas said,
18 May 2009 a 4:24 pm
Muchas gracias viejo me salvastes. Muy buen trabajo
Luis Roberto Serrano said,
19 junio 2009 a 9:55 pm
excelente rutina…muy buena solucion
Raul said,
24 julio 2009 a 8:17 am
Excelente….
Un servicio de nada que espera ficheros y envía mail, me ocupaba 12 Mb y ahora pasa a 1.
Carlos said,
25 julio 2009 a 10:45 am
EXCELENTE MUCHAS GRACIAS FUNCIONA DE MARAVILLA,
DESPUES CARGAR UN TREMENDA TABLA DE 500000 FILAS ME QUEDABA EN MEMORIA UNA CARGA DE 600MB AHHORA LIBERANDO TABLA QUEDA EN 20 MB JJJAJAJAJJ EXCELENTE
SysEdw said,
31 julio 2009 a 3:21 am
Felicitaciones, Q funciona como un programador desea que su sistema no pesara tanto que es el peor terror de todos nosotros.
Pedro Antonio Peláez said,
22 septiembre 2009 a 9:53 am
Para liberar memoria en Net de forma explicita se puede usar nulo, si asignas nulo a una array o a cualquier variable, que no necesite «dispose», el recolector la dara de baja inmediatamente de la memoria. Esto viene muy bien en algoritmos recursivos, que tienden a mantener memoria inutil acumulada.
La unica pega es que tienes que revisar el codigo a optimizar y asignar nulo a cada variable que ya no uses.
Un saludo 🙂
Luis said,
1 octubre 2009 a 8:34 pm
Hola,
Perdón mi ignorancia, pero alguien puede indicarme como hacer uso del método en una aplicación?
Saludos.
cristian said,
11 noviembre 2009 a 6:29 am
maravilloso…. redujo en mas de la mitad el uso de memoria de mi app..
notable…
kX said,
13 diciembre 2009 a 12:43 am
De 28mb baja a 5 cada vez que cierro una ventanita de configuraciones 😀
Muchas Gracias.
kX said,
13 diciembre 2009 a 12:46 am
wooow no habia visto, el post es del 2005! y nos sigue funcionando a muchos.
Eres poderoso Mercenario 😀
Mercenario said,
21 octubre 2012 a 1:47 pm
Y tres años después de tu comentario por lo visto le sigue funcionando a mucha gente, sigo estando impresionado el resultado de las «cuatro» lineas de código que decidí compartir, aunque no sean las mejores que haya hecho, la satisfacción que me ha dado por hacerlo lo recompensa.
el tito jari said,
21 enero 2010 a 3:13 pm
Muy buena la función. casi un 70% menos de memoria.
Enhorabuena.
Gracias!
Carlos Rosario said,
28 febrero 2010 a 7:58 pm
Excelente solución, simple pero efectiva.
Amador said,
1 marzo 2010 a 5:28 pm
Esto, chicos, una pregunta.
Donde y cuando colocais la llamada a la función, despues de cada procedimiento o función ‘pesados’?
Mercenario said,
1 marzo 2010 a 10:59 pm
Lo más correcto, desde mi punto de vista, es usarla cuando sometamos la aplicación/proceso/actuación a un segundo plano.
Estar descacheando/liberando/desechando memoria usada a cada paso de trabajo de carga no lo veo lógico, tambien depende de los procesos o funciones de carga «pesados» usados.
La memoria usada «de vez en cuando es cacheada» intencionalmente, respetad su consumo.
julio said,
4 junio 2010 a 12:27 am
muchisimas gracias funka ed maravilla!!!
Strong said,
4 junio 2010 a 4:49 am
y cuando debo de llamar a la funcion??
por ejemplo si estoy usando dataset? lo puedo llamar cuando cierre el formulario??
otra cosa si estoy trabajando en 64bit funciona??
gracias.
viper said,
7 julio 2010 a 10:26 pm
Felicidades…. no manches funciona de maravilla.
saludos.
miguelcr1982 said,
28 julio 2010 a 6:46 pm
Mae sos un monstruo, demasiado buena!!!, gracias!!!!
Ricardo said,
23 agosto 2010 a 10:02 pm
(BRASIL) Muito bom! Injeção na veia!
gochy said,
10 octubre 2010 a 12:05 am
Wooooooow!!!…
Muchas felicidades y graciaaaaas!!!…
Buscaba una solución así de buena como la tuya….
desde Costa Rica: Pura vidaaaaaaa!!!!
Freddy Espinoza said,
9 enero 2011 a 4:30 pm
la rutina libera memoria en forma correcta, sin embargo aún tengo el maldito error de Exception of type ‘System.OutOfMemoryException’ was thrown. al tratar de grabar en memoria un archivo PDF que estoy utilizando con la DLL de ASPPDF, ésta se cae en forma aleatoria al llegar a un límite que aún no tengo claro cual es.
Pedro said,
4 marzo 2011 a 11:39 am
Muy buena la rutina pero he observado que gracias a ella la columna (en el monitor de recursos de windows 7) espadcio de trabajo desciende fantasticamente, aunque la columna Asignación no baja tanto (columna que dice literalmente «cantidad de memoria reservada por el so para el proceso»). En mi caso tengo un vlc que reproduce fotos de un álbum y gracias a la función he conseguido que la columan espacio de trabajo baje. Sabe como bajar la columna de Asignación? Gracias
Matute said,
18 noviembre 2011 a 5:05 pm
me pasa lo mismo que a vos, tengo mi aplicacion que con el código baja la memoria de trabajo pero no la asignada, pudiste solucionar ese problema???
Jaime Alex said,
16 marzo 2011 a 4:09 am
Exelente Post…..
sergio aguirrezabala said,
16 junio 2011 a 1:32 am
Excelente (claro, sin ennrosques, 200% funcional) muy muy bien
Sercho said,
1 julio 2011 a 7:24 am
Muchas gracias, mi programa empezaba a subir muy rapido 10, 50, 100, 200, 400, 500 MB y asi en menos de un minuto!!! solo trabajaba con objetos Graphic pero los liberaba con dispose() y no servia 😛 ahora no pasa de los 3 MB 🙂
Excelente Gracias de nuevo! saludos!
Negron said,
2 julio 2011 a 2:38 am
Este codigo funciona en cualquier plataforma? Bien sea x86 o x64.
Sergio said,
12 julio 2011 a 4:15 pm
Muy, muy bueno. Me ha sacado de un buen apuro. Muchas gracias.
Federico said,
30 agosto 2011 a 7:09 pm
Gracias loco por tu aporte, muy bueno, mi aplicacion estaba volviendome loco, estaba por el mismo camino que vos, pero llegaste antes.
FEDE
Carlos said,
10 octubre 2011 a 3:58 pm
Muy buenas, gracias por el aporte solo que a mi no me funciona aun, estoy dando vueltas pero no logro ver el resultado esperado, uso vs team system 2008 (VB.net) y aparece un error
‘THE TARGETED VERSION OF COMPACT FRAMEWORK DOES NOT SUPPORT USING AUTO ‘
y en SetProcessWorkingSetSize(Mem.Handle, -1, -1) , Mem.handle no es miembro de system.diagnostic.process
help me please !!!
Carlos said,
10 octubre 2011 a 4:06 pm
de paso te comento mi hermano que yo lo que quiero es liberar memoria con una aplicacion para smartdevice… al querer llamar a otro formulario form2 desde un principal form1, lo logro ver claro, y desde el form2 regresar al form1 pero se van cargando en cada llamada los formularios en memoria de manera que me genera conflictos con datos mostrados anteriormente. Uso dispose() para liberar memoria pero el problema persiste.
He combinado varias formas una de ellas:
Dim objForm As New frmListaProductos
Try
objForm.ShowDialog()
frmListaProductos.ShowDialog()
Finally
Me.Close()
Me.Dispose()
System.GC.Collect()
otro es:
frmListaProductos.ShowDialog()
Me.Close()
Me.Dispose()
System.GC.Collect()
pero no doy !
luis said,
4 noviembre 2011 a 9:14 pm
no compila, me dice
el tipo process no esta definido 😦
finishmundiproductions said,
30 noviembre 2011 a 9:16 pm
Excelente, estaba utilizando hilos y demas cosas que hacian que mi aplicación no se cerrará. Con este programita se cierra sin problemas
Thanks
Albi said,
27 febrero 2012 a 5:25 pm
dos palabras Imp Presionante….
Jorge B. said,
10 May 2012 a 11:03 am
ESPECTACULAR. Me resolviste un problema terrible. Muchísimas gracias. Un GENIO.
katty said,
29 junio 2012 a 11:11 pm
Increíble, gracias x compartirlo.
Sandro said,
31 agosto 2012 a 9:51 pm
Obrigado, Gracias ótimo código!
Paul Ventura said,
21 octubre 2012 a 5:26 am
SetProcessWorkingSetSize(Mem.Handle, -1, -1) me da error dice se esperaba que fin de la instruccion???
Luis Basurto said,
1 May 2015 a 5:42 pm
Me imagino que solo copiaste y pegaste el codigo, el error es porque no se pega exactamente igual, debes poner esa instrucción en una sola linea separada de las demás instrucciones…
Revisa que te quede exactamente igual como esta publicado.
Edu said,
16 noviembre 2012 a 9:41 am
Si es verdad que reduce la memoria como indicais muchos, pero que pasa con la memoria virtual? Cuanto más reduce la memoria más aumenta al virtual…lo podeis ver en el administrador de tareas.
¿Alguien sabe si hay forma de reducir la memoria virtual de una forma parecida?
Mercenario said,
16 noviembre 2012 a 11:43 pm
Te recomiendo echar un ojo a los comentarios, algunos son interesantes sobre el tema.
Hace tiempo estuve mirando el tema de reducir la memoria de cacheo y si, se puede, pero no es nada recomendable. Si ya partimos de que esta forma de liberación no es «correcta» en si, el fuerce a liberación de memoria de cacheo lo es menos, pues es más interno.
Personalmente en el tema de memoria de cacheo prefiero dejar al SO administrarla, una cosa es liberación de memoria y otra forzarlo.
Lexy Lucin (@ChikitaLu24) said,
8 agosto 2013 a 10:46 pm
Hola! Tengo una sistema contable, al que le estoy añadiendo la parte comercial… Utilizo varios dataSets, dataTable, BindingSource, no puedo generarla por que me sale system.OutOfMemoryException…
Anthony said,
28 enero 2014 a 6:45 pm
Buenas, soy analista programador.
Un tiempo desarrolle una aplicacion con VS 2010 y sql server 2008 R2
las clases estaban contenidas dentro de la Aplicacion(no en una biblioteca de clases), pero esta consume menos memoria mientras esta sin uso
Actualmente estoy desarrollando otra aplicacion con VS 2012 y Sqlserver2008 R2 (las clases estan contenidas en una biblioteca de clases, pero esta esta consumiendo mas memoria mientras se esta sin uso, por su puesto esta aplicacion es mas grande que la primera
La pregunta es depende el tamaño de la aplicacion el consume de memoria, porq la verdad me intriga este detalle…
Saludos…!
Luis Basurto said,
1 May 2015 a 5:41 pm
Respuesta a: Paul Ventura said
21 octubre 2012 a 5:26 am
SetProcessWorkingSetSize(Mem.Handle, -1, -1) me da error dice se esperaba que fin de la instruccion???
Me imagino que solo copiaste y pegaste el codigo, el error es porque no se pega exactamente igual, debes poner esa instrucción en una sola linea separada de las demás instrucciones…
Revisa que te quede exactamente igual como esta publicado.
Carlos Otero said,
18 junio 2016 a 7:52 pm
Gracias por compartir este procedimiento, en la vida lo hubiera descubierto yo, programo en WPF, y es la única forma de liberar los formularios al cerrarlos, incluyendo esta función el el evento Closing. Gracias, de corazón.
Rod said,
24 julio 2016 a 5:34 am
Hola, eso está muy bien para WIN32, pero en 64 bits como seria?
Gracias
prueba4771 said,
4 septiembre 2021 a 4:00 pm
Excelente aporte 🙂