Al escribir aplicaciones de larga duración, el tipo de programas que pasarán la mayor parte del día minimizados en la barra de tareas o bandeja del sistema, puede volverse importante no dejar que el programa "se escape" con el uso de memoria.
Las dos columnas más a la derecha indican el uso de CPU (tiempo) y el uso de memoria. Si un proceso impacta severamente en cualquiera de estos, su sistema se ralentizará.
El tipo de cosa que con frecuencia impacta en el uso de la CPU es un programa que está en bucle (pregunte a cualquier programador que se haya olvidado de poner una declaración de "siguiente lectura" en un bucle de procesamiento de archivos). Ese tipo de problemas generalmente se corrige con bastante facilidad.
El uso de la memoria, por otro lado, no siempre es aparente y debe gestionarse más que corregirse. Supongamos, por ejemplo, que se está ejecutando un programa de tipo captura.
Este programa se usa durante todo el día, posiblemente para la captura telefónica en una mesa de ayuda, o por alguna otra razón. Simplemente no tiene sentido apagarlo cada veinte minutos y luego volver a encenderlo. Se usará durante todo el día, aunque a intervalos poco frecuentes.
Si ese programa se basa en un procesamiento interno pesado o tiene muchas ilustraciones en sus formularios, tarde o temprano su uso de memoria va a crecer, dejando menos memoria para otros procesos más frecuentes, aumentando la actividad de búsqueda y, en última instancia, ralentizando la computadora.
Digamos que va a diseñar un programa con el formulario principal y dos formularios adicionales (modales). Por lo general, dependiendo de su versión de Delphi, Delphi insertará los formularios en el unidad de proyecto (Archivo DPR) e incluirá una línea para crear todos los formularios al inicio de la aplicación (Aplicación. CreateForm (...)
Las líneas incluidas en la unidad del proyecto son del diseño de Delphi y son excelentes para las personas que no están familiarizadas con Delphi o que están empezando a usarlo. Es conveniente y útil. También significa que TODOS los formularios se crearán cuando se inicie el programa y NO cuando sean necesarios.
Dependiendo de qué se trate su proyecto y la funcionalidad que haya implementado, un formulario puede usar mucha memoria, por lo que las formas (o en general: objetos) solo deben crearse cuando sea necesario y destruirse (liberarse) tan pronto como ya no estén necesario.
Tanto "DialogForm" como "OccasionalForm" deben eliminarse de la lista de "Crear formularios automáticamente" y trasladarse a la lista de "Formularios disponibles".
Tenga en cuenta que la estrategia descrita aquí se basa en el supuesto de que el programa en cuestión es un programa de tipo "captura" en tiempo real. Sin embargo, se puede adaptar fácilmente para procesos de tipo por lotes.
Delphi ha tratado de minimizar esto y tiene su propia arquitectura de administración de memoria que usa bloques mucho más pequeños pero esto es prácticamente inútil en el entorno de Windows porque la asignación de memoria finalmente recae en el sistema operativo.
Una vez que Windows ha asignado un bloque de memoria a un proceso, y ese proceso libera el 99.9% de la memoria, Windows seguirá percibiendo que todo el bloque está en uso, incluso si solo se está utilizando un byte del bloque usado. La buena noticia es que Windows proporciona un mecanismo para solucionar este problema. El shell nos proporciona una API llamada SetProcessWorkingSetSize. Aquí está la firma:
Por definición, la función SetProcessWorkingSetSize establece los tamaños mínimo y máximo del conjunto de trabajo para el proceso especificado.
Esta API está diseñada para permitir una configuración de bajo nivel de los límites de memoria mínimo y máximo para el espacio de uso de memoria del proceso. Sin embargo, tiene un pequeño capricho incorporado que es muy afortunado.
Si los valores mínimos y máximos se establecen en $ FFFFFFFF, la API recortará temporalmente el tamaño establecido en 0, intercambiándolo de la memoria e inmediatamente como se recupera en la RAM, tendrá la mínima cantidad de memoria asignada (todo esto ocurre en un par de nanosegundos, por lo que para el usuario debería ser imperceptible).
Una llamada a esta API solo se realizará a intervalos determinados, no de forma continua, por lo que no debería haber ningún impacto en el rendimiento.
Ahora, verifique periódicamente el último recuento de ticks con "Ahora" y si la diferencia entre los dos es mayor que el período considerado como un período inactivo seguro, recorte la memoria.
Ahora decida después de qué período de tiempo considerará que el programa está inactivo. En mi caso, decidimos dos minutos, pero puede elegir el período que desee según las circunstancias.
Adaptar este método para largos tiempos de procesamiento o procesos por lotes es bastante simple. Normalmente tendrá una buena idea de dónde comenzará un proceso largo (por ejemplo, el comienzo de un ciclo de lectura a través de millones de registros de la base de datos) y dónde terminará (fin del ciclo de lectura de la base de datos).
Simplemente deshabilite su temporizador al comienzo del proceso y vuelva a habilitarlo al final del proceso.