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 escribió,
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 escribió,
18 octubre 2006 a 8:06 am
Acojonante …
jose escribió,
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 escribió,
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 escribió,
7 junio 2007 a 9:40 pm
Y no se exactamente como trabaja ese procedimiento…
Jijijijiji
Gracias…
Alfonso May escribió,
12 julio 2007 a 5:43 pm
Excelente…
tina escribió,
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 escribió,
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 escribió,
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 escribió,
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 escribió,
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 escribió,
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 escribió,
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 escribió,
14 marzo 2008 a 3:49 pm
Muchas gracias! me ha venido de lujo!
Marco Esparza escribió,
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 escribió,
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 escribió,
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 escribió,
20 abril 2009 a 6:58 pm
EXCELENTE LOCO!!! Le salvaste la vida a varias personas!
Giovanni Cedeño Prendas escribió,
18 mayo 2009 a 4:24 pm
Muchas gracias viejo me salvastes. Muy buen trabajo
Luis Roberto Serrano escribió,
19 junio 2009 a 9:55 pm
excelente rutina…muy buena solucion
Raul escribió,
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 escribió,
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 escribió,
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 escribió,
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 escribió,
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 escribió,
11 noviembre 2009 a 6:29 am
maravilloso…. redujo en mas de la mitad el uso de memoria de mi app..
notable…
kX escribió,
13 diciembre 2009 a 12:43 am
De 28mb baja a 5 cada vez que cierro una ventanita de configuraciones
Muchas Gracias.
kX escribió,
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 escribió,
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 escribió,
21 enero 2010 a 3:13 pm
Muy buena la función. casi un 70% menos de memoria.
Enhorabuena.
Gracias!
Carlos Rosario escribió,
28 febrero 2010 a 7:58 pm
Excelente solución, simple pero efectiva.
Amador escribió,
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 escribió,
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 escribió,
4 junio 2010 a 12:27 am
muchisimas gracias funka ed maravilla!!!
Strong escribió,
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 escribió,
7 julio 2010 a 10:26 pm
Felicidades…. no manches funciona de maravilla.
saludos.
miguelcr1982 escribió,
28 julio 2010 a 6:46 pm
Mae sos un monstruo, demasiado buena!!!, gracias!!!!
Ricardo escribió,
23 agosto 2010 a 10:02 pm
(BRASIL) Muito bom! Injeção na veia!
gochy escribió,
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 escribió,
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 escribió,
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 escribió,
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 escribió,
16 marzo 2011 a 4:09 am
Exelente Post…..
sergio aguirrezabala escribió,
16 junio 2011 a 1:32 am
Excelente (claro, sin ennrosques, 200% funcional) muy muy bien
Sercho escribió,
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 escribió,
2 julio 2011 a 2:38 am
Este codigo funciona en cualquier plataforma? Bien sea x86 o x64.
Sergio escribió,
12 julio 2011 a 4:15 pm
Muy, muy bueno. Me ha sacado de un buen apuro. Muchas gracias.
Federico escribió,
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 escribió,
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 escribió,
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 escribió,
4 noviembre 2011 a 9:14 pm
no compila, me dice
el tipo process no esta definido
finishmundiproductions escribió,
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 escribió,
27 febrero 2012 a 5:25 pm
dos palabras Imp Presionante….
Jorge B. escribió,
10 mayo 2012 a 11:03 am
ESPECTACULAR. Me resolviste un problema terrible. Muchísimas gracias. Un GENIO.
katty escribió,
29 junio 2012 a 11:11 pm
Increíble, gracias x compartirlo.
Sandro escribió,
31 agosto 2012 a 9:51 pm
Obrigado, Gracias ótimo código!
Paul Ventura escribió,
21 octubre 2012 a 5:26 am
SetProcessWorkingSetSize(Mem.Handle, -1, -1) me da error dice se esperaba que fin de la instruccion???
Edu escribió,
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 escribió,
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.