3

I'm trying to track down a memory leak on a Windows 7 Embedded Panel PC. Using Perfmon I can see that the "% committed bytes in use" grows steadily at a rate of 0.77% per hour when the app in question is running. On Win XP (not embedded) systems with the same conditions it doesn't grow at all.

I'm curious to know how this metric is calculated, with a view to adding my own monitoring and logging code to the app. Using the GlobalMemoryStatus API call I can get back several numbers, but no amount of crunching that I can think of gives me the same % result as Perfmon does when monitoring the "% committed bytes in use" counter.

How can I obtain this parameter?

Update

Sample code for Delphi follows. Just create a form, drop a memo and timer onto it. Tested under Win XP.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type TPerformanceInformation = packed record
    cb                 : DWORD ;
    CommitTotal        : integer;
    CommitLimit        : integer   ;
    CommitPeak         : Cardinal ;
    PhysicalTotal      : Cardinal ;
    PhysicalAvailable  : Cardinal   ;
    SystemCache        : Cardinal ;
    KernelTotal        : Cardinal ;
    KernelPaged        : integer ;
    KernelNonpaged     : Cardinal ;
    PageSize           : Cardinal ;
    HandleCount        : DWORD ;
    ProcessCount       : DWORD ;
    ThreadCount        : DWORD ;
    end ;

    TpPerformanceInformation = ^TPerformanceInformation ;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Memo1: TMemo;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1 ;

function GetPerformanceInfo (
    pPerformanceInformation : TpPerformanceInformation ;
    cb                      : dword) : integer ; stdcall ; external 'psapi.dll' ;

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);

var
    Status           : TMemoryStatus;
    PerformanceInfo  : TPerformanceInformation ;

begin
Memo1.Clear ;
Status.dwLength := sizeof(TMemoryStatus) ;
GlobalMemoryStatus (Status) ;

Memo1.Lines.Add (Format ('Total memory used (%%)  : %u',[Status.dwMemoryLoad])) ;

Memo1.Lines.Add (Format ('Physical memory used   : %u',[(Status.dwTotalPhys - Status.dwAvailPhys)])) ;
Memo1.Lines.Add (Format ('Physical memory left   : %u',[Status.dwAvailPhys])) ;
Memo1.Lines.Add (Format ('Total physical memory  : %u',[Status.dwTotalPhys])) ;
Memo1.Lines.Add (Format ('Total physical used (%%): %1.2f',[100.0 * (Status.dwTotalPhys - Status.dwAvailPhys) / Status.dwTotalPhys])) ;

Memo1.Lines.Add (Format ('Total page file        : %u',[Status.dwTotalPageFile])) ;
Memo1.Lines.Add (Format ('Page file used         : %u',[(Status.dwTotalPageFile - Status.dwAvailPageFile)])) ;
Memo1.Lines.Add (Format ('Page file left         : %u',[Status.dwAvailPageFile])) ;
Memo1.Lines.Add (Format ('Page file used  (%%)    : %1.2f',[100.0 * (Status.dwTotalPageFile - Status.dwAvailPageFile) / Status.dwTotalPageFile])) ;

if (GetPerformanceInfo (Addr (PerformanceInfo), Sizeof (TPerformanceInformation)) <> 0) then
    begin
    with PerformanceInfo do
        begin
        Memo1.Lines.Add (Format ('CommitTotal      : %u',[CommitTotal])) ;
        Memo1.Lines.Add (Format ('CommitLimit      : %u',[CommitLimit])) ;
        Memo1.Lines.Add (Format ('CommitPeak       : %u',[CommitPeak])) ;
        Memo1.Lines.Add (Format ('PhysicalTotal    : %u',[PhysicalTotal])) ;
        Memo1.Lines.Add (Format ('PhysicalAvailable: %u',[PhysicalAvailable])) ;
        Memo1.Lines.Add (Format ('SystemCache      : %u',[SystemCache])) ;
        Memo1.Lines.Add (Format ('KernelTotal      : %u',[KernelTotal])) ;
        Memo1.Lines.Add (Format ('KernelPaged      : %u',[KernelPaged])) ;
        Memo1.Lines.Add (Format ('KernelNonpaged   : %u',[KernelNonpaged])) ;
        Memo1.Lines.Add (Format ('PageSize         : %u',[PageSize])) ;
        Memo1.Lines.Add (Format ('HandleCount      : %u',[HandleCount])) ;
        Memo1.Lines.Add (Format ('ProcessCount     : %u',[ProcessCount])) ;
        Memo1.Lines.Add (Format ('ThreadCount      : %u',[ThreadCount])) ;
        end ;
    end ;
end;

end.

1 Answer 1

1

Check out GetPerformanceInfo(). It kicks back commit numbers.

3
  • Hmmmm @Jason - I don't suppose you could point me to how to call this from Delphi? I call it but the structure I pass doesn't get modified and after a few more calls I get an AV.
    – rossmcm
    May 3, 2011 at 8:28
  • Worked it out - question edited to provide example program
    – rossmcm
    May 4, 2011 at 21:09
  • Note: The Commit Limit and therefore the usage percentage is based on the current pagefile size. So if you have pagefile expansion enabled the limit can change. And of course the commit charge can change (up or down) at any moment. There is little reason for a program to query these numbers since the numbers can change right after you query them, but before you make any decisions based on them. May 1, 2017 at 17:35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .