Оптимизация использования памяти вашей Delphi-программой

При написании долго работающих приложений - вид программ, которые будут проводить большую часть дня, сводится к панели задач или системный трей, может стать важным не позволить программе «убежать» с использованием памяти.

Два крайних правых столбца указывают использование ЦП (время) и использование памяти. Если какой-либо из этих процессов серьезно повлияет на вашу систему, ваша система замедлится.

Вещь, которая часто влияет на загрузку процессора, - это программа, которая зацикливается (попросите любого программиста, который забыл поместить оператор «читать дальше» в цикл обработки файлов). Такие проблемы обычно довольно легко исправляются.

Использование памяти, с другой стороны, не всегда очевидно и требует более тщательного управления. Предположим, например, что программа типа захвата работает.

Эта программа используется в течение всего дня, возможно, для захвата телефона в службе поддержки или по какой-либо другой причине. Просто не имеет смысла выключать его каждые двадцать минут, а затем снова запускать. Он будет использоваться в течение дня, хотя и не часто.

instagram viewer

Если эта программа опирается на некоторую сложную внутреннюю обработку или имеет много иллюстраций на своих формах, рано или поздно ее использование памяти будет расти, оставляя меньше памяти для других более частых процессов, увеличивая активность подкачки и в конечном итоге замедляя работу компьютера.

Допустим, вы собираетесь разработать программу с основной формой и двумя дополнительными (модальными) формами. Как правило, в зависимости от вашей версии Delphi, Delphi собирается вставить формы в блок проекта (Файл DPR) и будет содержать строку для создания всех форм при запуске приложения (Приложение. CreateForm (...)

Линии, включенные в блок проекта, разработаны Delphi и отлично подходят для людей, которые не знакомы с Delphi или только начинают его использовать. Это удобно и полезно. Это также означает, что ВСЕ формы будут создаваться при запуске программы, а НЕ когда они необходимы.

В зависимости от того, о чем идет речь в вашем проекте и от функциональности, которую вы реализовали, форма может использовать много памяти, формы (или вообще: объекты) должны создаваться только при необходимости и уничтожаться (освобождаться), как только они перестают необходимо.

«DialogForm» и «OccasionalForm» необходимо удалить из списка «Автоматически создавать формы» и переместить в список «Доступные формы».

Обратите внимание, что стратегия, изложенная здесь, основана на предположении, что рассматриваемая программа является программой типа «захвата» в реальном времени. Однако его можно легко адаптировать к процессам периодического типа.

Delphi попытался минимизировать это и имеет свою собственную архитектуру управления памятью, которая использует гораздо меньшие блоки, но это практически бесполезен в среде Windows, потому что распределение памяти в конечном итоге зависит от операционной системы.

Как только Windows выделит блок памяти процессу, и этот процесс освобождает 99,9% памяти, Windows по-прежнему будет воспринимать весь используемый блок, даже если на самом деле используется только один байт блока используемый. Хорошей новостью является то, что Windows предоставляет механизм для устранения этой проблемы. Оболочка предоставляет нам API под названием SetProcessWorkingSetSize. Вот подпись:

По определению функция SetProcessWorkingSetSize устанавливает минимальный и максимальный размеры рабочего набора для указанного процесса.

Этот API предназначен для низкоуровневой установки минимальных и максимальных границ памяти для пространства использования памяти процессом. Тем не менее, в нем есть небольшая причуда, которая является наиболее удачной.

Если для минимального и максимального значений установлено значение $ FFFFFFFF, то API временно обрезает установленный размер до 0, выгружая его из памяти и немедленно по мере необходимости. возвращается в ОЗУ, ему будет выделен минимальный объем памяти (все это происходит в течение пары наносекунд, поэтому для пользователя это должно быть незаметны).

Вызов этого API будет производиться только через определенные промежутки времени, а не непрерывно, поэтому не должно быть никакого влияния на производительность.

Теперь периодически сверяйте счетчик последнего тика с «Сейчас» и, если разница между ними больше, чем период, который считается безопасным периодом простоя, обрезайте память.

Теперь решите, через какой промежуток времени вы сочтете программу бездействующей. В моем случае мы выбрали две минуты, но вы можете выбрать любой период в зависимости от обстоятельств.

Адаптировать этот метод для длительного времени обработки или пакетных процессов довольно просто. Обычно у вас есть хорошая идея, где начнется длительный процесс (например, начало цикла чтения миллионов записей базы данных) и где он закончится (конец цикла чтения базы данных).

Просто отключите свой таймер в начале процесса и включите его снова в конце процесса.