Liberando memoria inactiva
Mire qué aspecto de inocencia tiene el siguiente procedimiento. Parece que no sería capaz de matar una mosca:
procedure LiberarMemoria;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;
No obstante, ejecutándolo cada cierto tiempo puede lograr que esa aplicación que consume tanta memoria libere la memoria virtual que no está utilizando. La única condición: que esté ejecutando sobre Windows NT, 2000 o XP. Es decir, sobre una "verdadera" plataforma Win32.
¿No me cree? Hagamos entonces un experimento: ejecute cualquier aplicación sobre una de las versiones de Windows mencionadas, e inmediatamente pulse Ctrl+Alt+Del ... no para resetear, por supuesto, sino para que aparezca el Task Manager. Observe, en la lista de procesos activos, la cantidad de memoria que consume. Minimice la aplicación y restáurela, a continuación. Y vuelva a echarle un vistazo al Task Manager. Verá que se ha liberado una cantidad considerable de memoria. La aplicación puede ser el propio Delphi, pero nos vale incluso el Bloc de Notas.
Lo que sucede es que Win32, al minimizar una aplicación, llama a SetProcessWorkingSetSize para liberar toda la memoria virtual que no se encuentra activa en ese momento. En el caso de Delphi, y de las aplicaciones escritas en Delphi, el código de inicialización de las unidades puede llegar a ocupar bastante espacio, aunque solamente se necesite al principio. Y esa característica es la que intenta aprovechar LiberarMemoria.
La mala noticia es que SetProcessWorkingSetSize no llegó a implementarse sobre Windows 9x/ME. No pasa nada si ejecutamos esa función, pero para no perder el tiempo, el procedimiento LiberarMemoria comprueba el valor de la variable global Win32Platform.
¿Cuándo podemos llamar a LiberarMemoria? Lo más sencillo sería ejecutarla desde un timer, cada minuto, por ejemplo. Personalmente, no me preocupo por añadir esta mejora a las aplicaciones GUI, porque normalmente mis clientes las ejecutan sobre Windows 98SE. Pero para mí sí es útil en los servidores de capa intermedia, y en las aplicaciones CGI/ISAPI para Internet. En ambos casos, en vez de utilizar un timer rígido, mi costumbre es disparar la ejecución de LiberarMemoria desde un evento conveniente, como el evento AfterDispatch en aplicaciones para Internet, o AfterGetRecords y AfterApplyUpdates, en servidores de capa intermedia. En ese caso, añado un contador de llamadas dentro de esos eventos, y solamente llamo a LiberarMemoria cada cierto número de peticiones, para evitar los excesos.
|