2010-12-15 19 views
6

considerano l'applicazione di esempio successivoPerché l'utilizzo della memoria del mio programma non torna alla normalità dopo aver liberato memoria?

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('FastMem '+FormatFloat('#,', GetUsedMemoryFastMem)); 
     Writeln('Windows '+FormatFloat('#,', GetUsedMemoryWindows)); 
     Writeln(''); 
     Readln; 
end. 

i risultati restituiti dal app sono

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 

voglio sapere il motivo per cui i risultati del l'utilizzo della memoria sono diversi nel Before e After:

+0

@Optimal Cynic: è davvero intelligente? Sembra che la mia applicazione non restituisca circa 160 MB. Sui computer con 1 GB o RAM (o meno) non si tratta di uno spreco di RAM? Dettagli: http://stackoverflow.com/questions/4463979/my-program-never-releases-the-memory-back-why – Ampere

risposta

11

Qualsiasi gestore di memoria (incluso FastMM) incorre in un sovraccarico, altrimenti Delphi potrebbe aver appena utilizzato la gestione della memoria di Windows.

La differenza si osserva è la testa:

  • strutture che FastMM utilizza per tenere traccia di utilizzo della memoria,
  • pezzi di memoria che FastMM non aveva ancora tornare alla gestione della memoria di Windows per ottimizzare la memoria simili allocazioni in futuro.
+0

Puoi commentare, per favore, "Interno - Windows" valore – Branko

+0

@Branko per favore spiega il tuo commento, in quanto non capisco cosa ti aspetti da me. –

+0

@JeroenWiertPluimers probabilmente (solo indovinando) sta parlando del ritorno della domanda TestMemory di OP. 'All'interno ... Windows 3.637.248' – EMBarbosa

2

Perché il gestore della memoria sta facendo cose intelligenti in background per velocizzare le prestazioni.

+0

Ad esempio cosa? Se il processo rilascia la grande quantità di dati funzionante dalla memoria, non c'è motivo di conservare i riferimenti o qualsiasi altra cosa, quindi direi che idealmente la dimensione della memoria dovrebbe essere la stessa di prima dell'esecuzione. –

+1

Dipende idealmente se si preferisce la velocità alle dimensioni. –

+0

E intelligente dipende anche dal contesto. Un gestore di memoria estremamente intelligente potrebbe sia accelerare che ridurre l'ingombro di un'applicazione complessa e multithread, a scapito dello spreco di memoria nel caso "allocare, quindi immediatamente deallocare". Non ne so abbastanza del gestore della memoria di Delphi per sapere cosa sta facendo esattamente, ma so che non è possibile estrapolare dall'esempio nella domanda a qualsiasi applicazione di dimensioni ragionevoli. –

0

Come funziona getmem/malloc/free?

Heap Allocator - usati per malloc ...

1) assegna internamente pezzi di grandi dimensioni (in genere fino a 64K di 1 megabyte) di memoria e poi suddivide i pezzi fino a darvi gli oggetti 100byte e 200byte e stringhe nel programma. Quando si libera la memoria, tutto ciò che accade è il luogo in cui è stato assegnato dal buffer interno o il blocco è quindi contrassegnato come libero. NULLA REALMENTE SUCCEDE!

2) Quindi puoi pensare al HEAP come a una lista di grossi pezzi di memoria, e tutti gli oggetti nel tuo programma sono solo piccole parti di quei pezzi.

3) I grandi blocchi di memoria interni vengono liberati solo quando tutti gli oggetti al loro interno sono stati liberati, quindi il caso normale è che quando si liberano alcuni oggetti non accade nulla, tranne alcuni bit vengono contrassegnati come disponibili.

Questa è una descrizione abbastanza ingenua del sistema di heap, ma la maggior parte degli heap funziona in modo simile, ma fa molto più ottimizzazione di quella. Ma la tua domanda è: perché la memoria non va giù e la risposta è perché nulla viene effettivamente liberato. Le pagine interne di memoria vengono conservati per la successiva chiamata a "nuovi" o "malloc" ecc ...

PICTURE IT

ALL'INTERNO DEL MUCCHIO È UNO enorme blocco di 100Kb

You call "malloc(1000)" or "getmem(1000)" to get a 1K block of memory. 

Poi tutto ciò accade è che il blocco di memoria 1K viene prelevato dal blocco di memoria da 100kb lasciando 99K di memoria disponibile in quel blocco. Se continui a chiamare malloc o getmem, continuerà a dividere il blocco più grande fino a quando non avrà bisogno di un altro blocco più grande.

Ogni piccolo blocco di memoria allocato con una chiamata a malloc o getmem riceve in realtà circa 16 o 24 byte extra (in base all'allocatore) memoria extra. Quella memoria è bit che l'allocatore usa per sapere cosa viene assegnato e anche dove è allocato.

Problemi correlati