Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.197 Beiträge
 
Delphi 12 Athens
 
#4

AW: Speicherbenutzung nach wochenlanger Benutzung

  Alt 12. Jun 2012, 11:48
MSDN-Library durchsuchenGlobalMemoryStatusEx (ullAvailVirtual) oder du rechnest ein bissl mit den Werten rum, welche die FastMM (der DelphiMM) liefert.

ReportMemoryLeaksOnShutdown := True; wenn fast FastMM schon im Delphi integriert ist.

Delphi-Referenz durchsuchenGetMemoryManagerState
früher gab es noch Delphi-Referenz durchsuchenAllocMemCount, Delphi-Referenz durchsuchenAllocMemSize und Delphi-Referenz durchsuchenGetHeapStatus



[add]
Das Ding hatte ich vor Langem mal zusammengehackt. (wegen der Recordfunktionen sollte es wohl ab D2006/TDE laufen)
- mit .Init initialisieren
- z.B. alle 10 Sekunden .Update aufrufen
- und alle 5 Minuten .Execute (den Result-String in eine Logdatei)
Delphi-Quellcode:
type
  TProcessInfoX = record
    IntStart, IntCount: Cardinal; // GetTickCount
    // Process
    HandlesSum, HandlesMin, HandlesMax: Cardinal; // GetProcessHandleCount
    KernelTimeStart,
    KernelTimeLast, KernelTimeMin, KernelTimeMax: Int64{TFileTime}; // GetProcessTimes(lpKernelTime)
    UserTimeStart,
    UserTimeLast, UserTimeMin, UserTimeMax: Int64{TFileTime}; // GetProcessTimes(lpUserTime)
    MemorySum, MemoryMin, MemoryMax: UInt64; // GlobalMemoryStatusEx(ullAvailVirtual)
    // Global
    MemoryLoadSum, MemoryLoadMin, MemoryLoadMax: Cardinal; // GlobalMemoryStatusEx(dwMemoryLoad)
    FreeRAMSum, FreeRAMMin, FreeRAMMax: UInt64; // GlobalMemoryStatusEx(ullAvailPhys)
    PageFileSum, PageFileMin, PageFileMax: UInt64; // GlobalMemoryStatusEx(ullAvailPageFile)
    //
    procedure Init; // bei Programmstart initialisieren
    procedure Update; // zwischendurch updaten, für die Min/Max-Berechnung
    function Execute: String; // am Ende eines Messintervalls alles Berechnen und neues Intervall beginnen
  end;

{ TProcessInfoX }

procedure TProcessInfoX.Init;
begin
  FillChar(Self, SizeOf(Self), 0);
  IntStart := GetTickCount;
  IntCount := 1;
  Execute;
end;

procedure TProcessInfoX.Update;
var
  H: THandle;
  Handles: Cardinal;
  KernelTime, UserTime, X: Int64{TFileTime};
  _Time: TFileTime;
  MemoryStatus: TMemoryStatusEx;
begin
  Inc(IntCount);
  H := GetCurrentProcess;
  if GetProcessHandleCount(H, Handles) then begin
    Inc(HandlesSum, Handles);
    if HandlesMin > Handles then HandlesMin := Handles;
    if HandlesMax < Handles then HandlesMax := Handles;
  end;
  if GetProcessTimes(H, _Time, _Time, TFileTime(KernelTime), TFileTime(UserTime)) then begin
    X := KernelTime - KernelTimeLast;
    KernelTimeLast := KernelTime;
    if KernelTimeMin > X then KernelTimeMin := X;
    if KernelTimeMax < X then KernelTimeMax := X;
    X := UserTime - UserTimeLast;
    UserTimeLast := UserTime;
    if UserTimeMin > X then UserTimeMin := X;
    if UserTimeMax < X then UserTimeMax := X;
  end;
  MemoryStatus.dwLength := SizeOf(MemoryStatus);
  if GlobalMemoryStatusEx(MemoryStatus) then
    with MemoryStatus do begin
      X := ullTotalVirtual - ullAvailVirtual;
      Inc(MemorySum, X);
      if MemoryMin > X then MemoryMin := X;
      if MemoryMax < X then MemoryMax := X;
      Inc(MemoryLoadSum, dwMemoryLoad);
      if MemoryLoadMin > dwMemoryLoad then MemoryLoadMin := dwMemoryLoad;
      if MemoryLoadMax < dwMemoryLoad then MemoryLoadMax := dwMemoryLoad;
      X := ullAvailPhys;
      Inc(FreeRAMSum, X);
      if FreeRAMMin > X then FreeRAMMin := X;
      if FreeRAMMax < X then FreeRAMMax := X;
      X := ullTotalPageFile - ullAvailPageFile;
      Inc(PageFileSum, X);
      if PageFileMin > X then PageFileMin := X;
      if PageFileMax < X then PageFileMax := X;
    end;
end;

function TProcessInfoX.Execute: String;
function RD(i: UInt64): Integer; inline;
  begin
    Result := (i + 787200) shr 20;
  end;
var
  H: THandle;
  _Time: TFileTime;
  KernelTime, UserTime: Int64{TFileTime};
  KernelTimeMean, UserTimeMean: Int64{TFileTime};
  Handles, HandlesMean, MemoryLoadMean: Cardinal;
  ProcessLoad, ProcessUserT, IntTime: Cardinal;
  MemoryMean, FreeRAMMean, PageFileMean: UInt64;
  MemoryStatus: TMemoryStatusEx;
  New: TProcessInfoX;
  MMS: TMemoryManagerState;
  UsedDelphiMM, ReservedDelphiMM: Cardinal;
  i: Integer;
begin
  if (GetTickCount - IntStart) > 100 then
    Update;
  IntTime := GetTickCount - IntStart;
  if IntTime <= 0 then
    IntTime := 1; // kein DivByZZero
  H := GetCurrentProcess;

  FillChar(New, SizeOf(Self), 0);
  New.IntStart := GetTickCount;
  New.IntCount := 1;

  if GetProcessHandleCount(H, Handles) then begin
    HandlesMean := HandlesSum div IntCount;
    New.HandlesSum := Handles;
    New.HandlesMin := Handles;
    New.HandlesMax := Handles;
  end else
    HandlesMean := 0;

  if GetProcessTimes(H, _Time, _Time, TFileTime(KernelTime), TFileTime(UserTime)) then begin
    KernelTimeMean := KernelTime - KernelTimeStart;
    UserTimeMean := UserTime - UserTimeStart;
    ProcessLoad := ((UserTimeMean + KernelTimeMean) div 100) div IntTime;
    ProcessUserT := ( UserTimeMean div 100) div IntTime;
    New.KernelTimeStart := KernelTime;
    New.UserTimeStart := UserTime;
    New.KernelTimeLast := KernelTime;
    New.UserTimeLast := UserTime;
    New.KernelTimeMin := High(Int64);
    New.UserTimeMin := High(Int64);
    New.KernelTimeMax := 0;
    New.UserTimeMax := 0;
  end else begin
    ProcessLoad := 0;
    ProcessUserT := 0;
  end;

  MemoryStatus.dwLength := SizeOf(MemoryStatus);
  if GlobalMemoryStatusEx(MemoryStatus) then begin
    with MemoryStatus do begin
      MemoryMean := MemorySum div IntCount;
      MemoryLoadMean := MemoryLoadSum div IntCount;
      FreeRAMMean := FreeRAMSum div IntCount;
      PageFileMean := PageFileSum div IntCount;
      New.MemorySum := ullTotalVirtual - ullAvailVirtual;
      New.MemoryLoadSum := dwMemoryLoad;
      New.FreeRAMSum := ullAvailPhys;
      New.PageFileSum := ullTotalPageFile - ullAvailPageFile;
      New.MemoryMin := New.MemorySum;
      New.MemoryLoadMin := New.MemoryLoadSum;
      New.FreeRAMMin := New.FreeRAMSum;
      New.PageFileMin := New.PageFileSum;
      New.MemoryMax := New.MemorySum;
      New.MemoryLoadMax := New.MemoryLoadSum;
      New.FreeRAMMax := New.FreeRAMSum;
      New.PageFileMax := New.PageFileSum;
    end;
  end else begin
    MemoryMean := 0;
    MemoryLoadMean := 0;
    FreeRAMMean := 0;
    PageFileMean := 0;
  end;


  GetMemoryManagerState(MMS);
  UsedDelphiMM := MMS.TotalAllocatedMediumBlockSize + MMS.TotalAllocatedLargeBlockSize;
  For i := 0 to NumSmallBlockTypes - 1 do
    Inc(UsedDelphiMM, MMS.SmallBlockTypeStates[i].InternalBlockSize * MMS.SmallBlockTypeStates[i].AllocatedBlockCount);
  ReservedDelphiMM := MMS.ReservedMediumBlockAddressSpace + MMS.ReservedLargeBlockAddressSpace;

  Result := Format('CPU: %2d %% (%2d) Memory: %4d MB (%4d-%4d) MemoryLoad: %2d %% (%2d-%2d) DelphiMM: %4d MB (res %3d MB) '
    + 'FreeRAM: %4d MB (%4d-%4d) PageFile: %4d MB (%4d-%4d) Handles: %3d (%3d-%3d)', [
    ProcessLoad, ProcessUserT,
    RD(MemoryMean), RD(MemoryMin), RD(MemoryMax),
    MemoryLoadMean, MemoryLoadMin, MemoryLoadMax,
    RD(UsedDelphiMM), RD(ReservedDelphiMM),
    RD(FreeRAMMean), RD(FreeRAMMin), RD(FreeRAMMax),
    RD(PageFileMean), RD(PageFileMin), RD(PageFileMax),
    HandlesMean, HandlesMin, HandlesMax]);

  Self := New;
end;
(als Zitat sieht der Code hübscher aus)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (12. Jun 2012 um 12:00 Uhr)
  Mit Zitat antworten Zitat