BERDAFLEX Software Systems
Главная > Delphi > Менеджер памяти

Менеджер памяти

История переиздания
Издание 1.0 2003.11.20 Сергей Бердачук

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

В результате решения этой проблемы, я попытался создать модуль освобождения оперативной памяти, который вызывался бы с некоторой периодичностью или перед выполнением длительных, ресурсоёмких операций. Отсутствие информации по работе стандартного менеджера привело к следующему решению: «Нужно попытаться выделить достаточно большой участок памяти под какой-нибудь объект, а затем освободить его. При этом менеджер памяти Windows сбрасывает часть данных в своп». Пример функции, реализующей данный алгоритм:

function BS_FreeMem(const aBufSize:Integer):boolean;
var
  tmpBuffer: PChar;
begin
  result:=true;
  try
    //Выделяем буфер заданного размера
    GetMem(tmpBuffer, aBufSize);
    try
      //Заполняем буфер нулями
      // для имитации его использования
      FillChar(tmpBuffer^, aBufSize, 0); 
    finally
      FreeMem(tmpBuffer);
    end;
  except
    result:=false;
  end;
end;

На машинах с операционной системой класса Windows Nt, можно попробовать воспользоваться API функцией SetProcessWorkingSetSize. Вызов данной функции со значениями параметров dwMinimumWorkingSetSize и dwMaximumWorkingSetSize, равными $FFFFFFFF вызывает сброс страниц памяти, занятых процессом в своп файл.

Например:

SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);

Вызывать созданную фунцию можно по таймеру, например:
procedure TfrmMain.DigitalClockMinute(Sender: TObject; DDGTime: TDateTime);
var
  MemStat:TMemoryStatus;
  fMemPercent:Extended;
  bufSize:Variant;
  oldHint:String;
  oldCursor:TCursor;
begin
  //Глобальная переменняя,
  //определяющая активность функции
  if gInternalMemManager then
  begin
    MemStat.dwLength := SizeOf(TMemoryStatus);
    GlobalMemoryStatus(MemStat);
    fMemPercent:=(MemStat.dwTotalPhys-MemStat.dwAvailPhys);
    fMemPercent:=fMemPercent*100/MemStat.dwTotalPhys;
    //Вызываем фунцию, при загрузке памяти более 90%
    if fMemPercent > 90 then
    try
      oldHint:=Application.Hint;
      oldCursor:=Screen.Cursor;
      Screen.Cursor:=crHourGlass;
      Application.Hint:='Освобождение оперативной памяти..';
      //вычисляем размер выделяемого буффера
      bufSize:=(MemStat.dwTotalPhys-MemStat.dwAvailPhys)/2;
      BS_FreeMem(Integer(bufSize));
    finally
      Application.Hint:=oldHint;
      Screen.Cursor:=oldCursor;
    end;
  end;  
end;

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

Скачать модуль bs_lib

Rambler's Top100 Рейтинг@Mail.ru