Дорогой Алтарь, я поражен тем, насколько ты не уверен в своих догадках и как ты не слушаешь то, что люди говорили тебе много раз прежде.
Давайте уточним некоторые вещи.Управление памятью 101. Пожалуйста, внимательно прочитайте.
При выделении памяти в Delphi задействуются два менеджера памяти.
Менеджер системной памяти
Первый - менеджер системной памяти,Он встроен в Windows и дает память в страницах размером 4 КБ.
Но он не всегда дает вам память в ОЗУ (или физическую память).Ваши данные могут храниться на жестком диске и считываться каждый раз, когда вам необходим доступ к ним.Это очень медленно.
Другими словами, представьте, что у вас 512 МБ физической памяти.Вы запускаете две программы, каждая из которых запрашивает 1 ГБ памяти.Что делает ОС?
Она удовлетворяет оба запроса.Оба приложения получают по 1 ГБ памяти.Оба думают, что вся память «в памяти».Но на самом деле в оперативной памяти можно хранить только 512 Мб.Остальное хранится в файле подкачки, хотя ваше приложение этого не знает.Это просто работает медленно.
Размер рабочего набора
Теперь, какой «размер рабочего набора» вы измеряете?
Это часть выделенной памяти, которая сохраняетсяв ОЗУ.
Если у вас есть приложение, которое выделяет 1 ГБ памяти, и у вас есть только 512 МБ ОЗУ, то размер рабочего набора будет 512 МБ.Хотя он «использует» 1 ГБ памяти!
Когда вы запускаете другое приложение, которому требуется память, ОС автоматически освобождает часть ОЗУ, перемещая редко используемые блоки «памяти» на жесткий диск.
Распределение виртуальной памяти останется прежним, но на жестком диске будет больше страниц, а в оперативной памяти - меньше.Размер рабочего набора уменьшится.
Исходя из этого, к этому моменту вы должны были понять, что пытаться минимизировать размер рабочего набора бессмысленно.Вы ничего не достигаете.Вы не освобождаете память ни в каком смысле .Вы просто выгружаете данные на жесткий диск.
Но система сделает это автоматически, когда это необходимо.И нет смысла выделять место в оперативной памяти, пока она не понадобится.Вы просто замедляете работу своего приложения, вот и все.
TLDR : «Размер рабочего набора» не означает «сколько памяти использует приложение».Это "сколько готово прямо сейчас".Не пытайтесь свести его к минимуму, вы только усугубляете ситуацию.
Диспетчер памяти Delphi
ОС предоставляет вам виртуальную память на страницах по 4 КБ.Но часто вам это нужно в гораздо меньших порциях.Например, 4 байта для вашего целого числа или 32 байта для некоторой структуры.Решение?
Менеджер памяти приложений, такой как FastMM или BorlandMM или др.
Его задача состоит в том, чтобы выделять память на страницах из операционной системы, а затем выдавать небольшие куски этих страниц, когда выэто нужно.
Другими словами, когда вы запрашиваете 14 байтов памяти, вот что происходит:
- Вы запрашиваете у FastMM 14 байтов памяти.
- FastMM запрашивает у ОС 1 страницу памяти (4096 байт).
- ОС выделяет одну страницу памяти, резервируя ее с помощью ОЗУ (она хранится в реальном ОЗУ).
- FastMM сохраняет эту страницу, обрезает 14 байт и выдает вам.
Когда вы запрашиваете еще 14 байт, FastMM просто обрезает еще 14 байт с той же страницы.
Что происходит, когда вы освобождаетеобъем памяти?То же самое в обратном направлении:
- Вы освобождаете 14 байтов для FastMM.Ничего не происходит.
- Вы освобождаете еще 14 байтов.FastMM видит, что выделенная им 4096-байтовая страница теперь полностью не используется.
- Поэтому она освобождает страницу, возвращая ее в систему.
Стоит отметить, что FastMM не может освободить только 14 байт для системы.Это должно освободить память в страницах.Пока вся страница не будет свободной, FastMM не сможет ничего сделать.Никто не может.
Итак, почему размер моего рабочего набора такой большой, хотя я все выпустил?
Во-первых, размер вашего рабочего набора не тот, который вы должны измерять. Потребление виртуальной памяти есть. Но если у вас большой размер рабочего набора, потребление виртуальной памяти также будет высоким.
В чем проблема? Вы должны быть в состоянии понять это.
Допустим, вы выделяете 1 КБ, а затем 3 КБ памяти. Сколько виртуальной памяти вы выделили? 4кб, 1 стр.
Теперь вы выпускаете 3Kb. Сколько виртуальной памяти вы используете сейчас? 1Kb? Нет, это все еще 1 страница. Вы не можете выделить менее 1 страницы из системы. Вы все еще используете 4096 байт виртуальной памяти.
Представьте, если вы сделаете это 1000 раз. 1 КБ, 3 КБ, 1 КБ, 3 КБ, 1 КБ, 3 КБ и так далее. Вы выделяете 1000 * 4kb = 4 МБ, а затем освобождаете все части по 3 КБ. Сколько виртуальной памяти вы используете сейчас?
Еще 4 мб. Потому что сначала вы выделили 1000 страниц. Из каждой страницы вы взяли куски 1 КБ и 3 КБ. Даже если вы освободите блоки размером 3 КБ, блоки размером 1 КБ будут продолжать сохранять каждую страницу, выделенную вами, в памяти. И каждая страница занимает 4 КБ виртуальной памяти.
Менеджер памяти не может волшебным образом "переместить" все ваши куски по 1 КБ вместе. Это невозможно, потому что на их виртуальные адреса можно ссылаться откуда-то в коде. Это не черта FastMM.
Но почему с BorlandMM все работает лучше?
Совпадение. Может быть, так получилось, что BorlandMM дает вам память немного иначе, чем FastMM. Следующее, что вы знаете, вы что-то изменили в своем приложении, и BorlandMM работает так же, как FastMM. Диспетчер памяти не может полностью предотвратить этот эффект, который называется фрагментацией памяти.
Так что мне делать?
Короткий ответ: не так много, пока это вас не беспокоит.
Видите ли, с современными операционными системами вы на самом деле не используете чью-либо оперативную память. В соответствии с вышеизложенным, ОС автоматически заменяет ваши страницы, когда ей требуется ОЗУ для других приложений. Это не должно быть проблемой.
И «лишняя» память не теряется. Хотя страницы распределены, 3 КБ каждого помечается как «свободный». В следующий раз, когда вашему приложению понадобится память, диспетчер памяти будет использовать это пространство.
Но если вы действительно хотите помочь, вы должны реорганизовать свои ассигнования так, чтобы те, которые вы планируете сохранить, выполнялись первыми, а те, которые вы скоро освободите, были распределены после этого.
Как это: 1kb, 1kb, 1kb, ..., 3kb, 3kb, 3kb ...
Если вы сейчас освободите все блоки по 3 КБ, ваше потребление виртуальной памяти значительно снизится.
Это не всегда возможно. Если это невозможно, то просто ничего не делай. Это более или менее хорошо, как это.
И П.С.
Во-первых, вам не следует выделять 500 форм. Это явно не путь. Исправьте это, и вам даже не нужно будет думать о распределении и освобождении памяти.
Надеюсь, это прояснит ситуацию, потому что четыре сообщения на одну и ту же тему, честно говоря, это слишком много.