2010-12-15 9 views
6

considerar la siguiente aplicación de ejemplo¿Por qué el uso de la memoria de mi programa no vuelve a la normalidad después de liberar la 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. 

los resultados devueltos por la aplicación son

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 

Quiero saber por qué los resultados del uso de la memoria son diferentes en el Before y After:

+0

@Optimal Cynic - ¿es realmente inteligente? Parece que mi aplicación no devuelve unos 160 MB. En computadoras con 1GB o RAM (o menos) ¿no es esto una pérdida de RAM? Detalles: http://stackoverflow.com/questions/4463979/my-program-never-releases-the-memory-back-why – Ampere

Respuesta

11

Cualquier administrador de memoria (incluyendo FastMM) incurre en cierta sobrecarga, de lo contrario podría haber Delphi acaba de utilizar la gestión de memoria de Windows.

La diferencia se observa es la sobrecarga:

  • estructuras que FastMM utiliza para realizar un seguimiento del uso de la memoria,
  • trozos de memoria que FastMM sin embargo, no regresó a la gestión de memoria de Windows para optimizar memoria similar asignaciones en el futuro.
+0

Podría comentar, por favor, el valor "Dentro de Windows" – Branko

+0

@Branko por favor explique su comentario, ya que no entiendo lo que espera de mí. –

+0

@JeroenWiertPluimers probablemente (adivinando) que está hablando de la devolución de la aplicación TestMemory de OP. 'Dentro ... Windows 3.637.248' – EMBarbosa

2

Porque el administrador de memoria está haciendo cosas inteligentes en segundo plano para acelerar el rendimiento.

+0

Por ejemplo, ¿qué? Si el proceso libera la gran cantidad de datos de la memoria, entonces no hay razón para guardar referencias o lo que sea, por lo que yo diría que, idealmente, el tamaño de la memoria debería ser el mismo que antes de la ejecución. –

+1

Lo ideal es que prefiera si prefiere la velocidad sobre el tamaño. –

+0

Y listo también depende del contexto. Un administrador de memoria extremadamente inteligente podría acelerar y disminuir la huella de una aplicación grande y compleja de subprocesos múltiples, a expensas de desperdiciar memoria en el caso "asignar, luego desasignar inmediatamente". No sé lo suficiente sobre el administrador de memoria de Delphi para saber exactamente qué está haciendo, pero sí sé que no se puede extrapolar del ejemplo de la pregunta a ninguna aplicación de tamaño razonable. –

0

¿Cómo funciona GetMem/malloc/libre?

Montón Allocator - Tal como se utiliza por malloc ...

1) asigna internamente trozos grandes (normalmente 64 K hasta 1 Megabyte) de memoria y luego sub-divide los trozos hasta que dan los objetos 100byte y 200byte y cadenas en el programa. Cuando libera memoria, todo lo que sucede es el lugar desde el que se asignó en el búfer interno o el fragmento se marca como libre. ¡NADA REALMENTE SUCEDE!

2) Por lo tanto se puede pensar de la pila como una lista de grandes trozos de memoria, y todos los objetos en su programa son sólo pequeñas partes de los trozos.

3) Los grandes trozos internos de memoria solo se liberan cuando se liberan todos los objetos dentro de ellos, por lo que lo normal es que cuando sueltes algún objeto no ocurra nada, salvo que algunos bits estén marcados como disponibles.

Esa es una descripción bastante ingenua del sistema de lixiviación, pero la mayoría de los montones funcionan de una manera similar, pero hacen mucho más que eso optimización. Pero su pregunta es por qué la memoria no baja y la respuesta es porque nada se libera realmente. Las páginas internas de la memoria se guardan para la siguiente llamada a la "nueva" o "malloc", etc ...

Picture It

DENTRO montón es una cuadra ENORME DE 100 Kb

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

Entonces todo eso sucede es que el bloque de memoria 1K se toma del bloque de 100kb de memoria dejando 99K de memoria disponible en ese bloque. Si continúa llamando malloc o getmem, seguirá dividiendo el bloque más grande hasta que necesite otro bloque más grande.

Cada pequeño bloque de memoria asignada con una llamada a malloc o GetMem realidad recibe alrededor de 16 o 24 bytes adicionales (en función de asignador) de memoria adicional. Esa memoria es bits que el asignador utiliza para saber qué se asigna y también dónde se asigna.

Cuestiones relacionadas