Why doesn't my program's memory usage return to normal after I free memory?
consider the next sample application
program TestMemory;
{$APPTYPE CONSOLE}
uses
PsAPI,
Windows,
SysUtils;
function GetUsedMemoryFastMem: cardinal;
var
st: TMemoryManagerState;
sb: TSmallBlockTypeState;
begin
GetMemoryManagerState(st);
result := st.TotalAllocatedMediumBlockSize + st.TotalAllocatedLargeBlockSize;
for sb in st.SmallBlockTypeStates do
begin
result := result + sb.UseableBlockSize * sb.AllocatedBlockCount;
end;
end;
function GetUsedMemoryWindows: longint;
var
ProcessMemoryCounters: TProcessMemoryCounters;
begin
Result:=0;
ProcessMemoryCounters.cb := SizeOf(TProcessMemoryCounters);
if GetProcessMemoryInfo(GetCurrentProcess(), @ProcessMemoryCounters, ProcessMemoryCounters.cb) then
Result:= ProcessMemoryCounters.WorkingSetSize
else
RaiseLastOSError;
end;
procedure Test;
const
Size = 1024*1024;
var
P : Pointer;
begin
GetMem(P,Size);
Writeln('Inside');
Writeln('FastMem '+FormatFloat('#,', GetUsedMemoryFastMem));
Writeln('Windows '+FormatFloat('#,', GetUsedMemoryWindows));
Writeln('');
FreeMem(P);
end;
begin
Writeln('Before');
Writeln('FastMem '+FormatFloat('#,', GetUsedMemoryFastMem));
Writeln('Windows '+FormatFloat('#,', GetUsedMemoryWindows));
Writeln('');
Test;
Writeln('After');
Writeln('F开发者_如何学CastMem '+FormatFloat('#,', GetUsedMemoryFastMem));
Writeln('Windows '+FormatFloat('#,', GetUsedMemoryWindows));
Writeln('');
Readln;
end.
the results returned by the app are
Before
FastMem 1.844
Windows 3.633.152
Inside
FastMem 1.050.612
Windows 3.637.248
After
FastMem 2.036
Windows 3.633.152
I wanna know why the results of the memory usage are different in the Before
and After
:
Any memory manager (including FastMM) incurs some overhead, otherwise Delphi could have just used the Windows memory management.
The difference you observe is the overhead:
- structures that FastMM uses to keep track of memory usage,
- pieces of memory that FastMM did not yet return to the Windows memory management to optimize similar memory allocations in the future.
Because the memory manager is doing clever things in the background to speed up performance.
How does it work getmem/malloc/free?
Heap Allocator - As used by malloc...
1) Internally allocates large chunks(typically 64K up to 1Megabyte) of memory and then sub-divides the chunks up to give you the 100byte and 200byte objects and strings in the program. When you free memory all that happens is the place where it was allocated from in the internal buffer or chunk is then marked as free. NOTHING ACTUALLY HAPPENS!
2) So you can think of the HEAP as a list of big chunks of memory, and all the objects in your program are just little parts of those chunks.
3) The big internal chunks of memory are only freed when all the objects inside them have been freed, so the usual case is that when you free some object that nothing actually happens except some bits get marked as being available.
That is a fairly naive description of the heap system, but most heaps work in a similar way, but do a lot more optimization than that. But your question is why does the memory not go down and the answer is because nothing actually gets freed. The internal pages of memory are retained for the next call to "new" or "malloc" etc...
PICTURE IT
INSIDE HEAP IS ONE HUGE BLOCK OF 100Kb
You call "malloc(1000)" or "getmem(1000)" to get a 1K block of memory.
Then all that happens is that the 1K block of memory is taken from the 100kb block of memory leaving 99K of memory available in that block. If you keep calling malloc or getmem then it will just keep dividing the larger block up until it needs another larger block.
Each little block of memory allocated with a call to malloc or getmem actually gets about 16 or 24 extra bytes(depending on allocator) extra memory. That memory is bits that the allocator uses to know what is allocated and also where it is allocated.
精彩评论