TMemoryStatusEx - zwracane dane nie zgadzają się z rzeczywistością

0

Hej,
Mam tu taki problem. Potrzebuję pobrać informacje o pamięci systemu (dla Windows XP oraz Win7/8).
Poniżej prezentuję kod, który teoretycznie powinien to zadanie spełnić (przykład na Win8.1 x64). Jest jeden szkopuł.
Według mnie, prezentowane dane nie są zgodne z tym co podaje systemowy programik informacji o systemie.
Start->Uruchom->msinfo32.exe. Porównajcie wyniki poniższego programu oraz to co podaje system.

program Project1;

{$APPTYPE CONSOLE}

uses
  Windows,
  Classes,
  SysUtils;

type
  DWORDLONG = UInt64;

  PMemoryStatusEx = ^TMemoryStatusEx;
  TMemoryStatusEx = packed record
    dwLength: DWORD;
    dwMemoryLoad: DWORD;
    ullTotalPhys: DWORDLONG;
    ullAvailPhys: DWORDLONG;
    ullTotalPageFile: DWORDLONG;
    ullAvailPageFile: DWORDLONG;
    ullTotalVirtual: DWORDLONG;
    ullAvailVirtual: DWORDLONG;
    ullAvailExtendedVirtual: DWORDLONG;
  end;

function GlobalMemoryStatusEx(var lpBuffer: TMemoryStatusEx): BOOL; stdcall; external kernel32;

procedure Main;
var
  MemStatus: TMemoryStatusEx;
begin
  // initialize the structure
  FillChar(MemStatus, SizeOf(MemStatus), 0);
  MemStatus.dwLength := SizeOf(MemStatus);
  // check return code for errors
  Win32Check(GlobalMemoryStatusEx(MemStatus));

  Writeln(Format('Rozmiar: x%d', [MemStatus.dwLength]));
  Writeln(Format('Pamiec uzywana: %d', [MemStatus.dwMemoryLoad]) + '%');

  Writeln(Format('Calkowita Pamiec Fizyczna: %f', [(MemStatus.ullTotalPhys /1024 /1024/1024)]) + ' GB');
  Writeln(Format('Dostepna Pamiec Fizyczna: %f', [(MemStatus.ullAvailPhys /1024 /1024/1024)]) + ' GB');

  Writeln(Format('Calkowity Rozmiar Pliku Wymiany: %f', [MemStatus.ullTotalPageFile /1024 /1024/1024]) + ' GB');
  Writeln(Format('Dostepny Rozmiar Pliku Wymiany: %f', [MemStatus.ullAvailPageFile /1024 /1024/1024]) + ' GB');


  Writeln(Format('Calkowita Pamiec Wirtualna: %f', [MemStatus.ullTotalVirtual /1024 /1024/1024]) + ' GB');
  Writeln(Format('Dostepna Pamiec Wirtualna: %f', [MemStatus.ullAvailVirtual /1024 /1024/1024]) + ' GB');
  Writeln(Format('COS = Zawsze 0: %d', [MemStatus.ullAvailExtendedVirtual]));
  Readln;

end;

begin
  try
    Main;
  except
    on E: Exception do
    begin
      ExitCode := 1;
      Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
    end;
  end;
end.

Teraz tak. Pamiec uzywana, Calkowita Pamiec Fizyczna, Dostepna Pamiec Fizyczna są OK.

Problemy:

  1. msinfo32.exe podaje ze "Całkowity rozmiar pamięci wirtualnej"=9,25GB -> program jednak taką wartość zwraca z MemStatus.ullTotalPageFile (jakby odwrotnie!)

  2. msinfo32.exe podaje ze "Dostępna pamięć wirtualna"=5,81GB -> program jednak taką wartość zwraca z MemStatus.ullAvailPageFile (jakby odwrotnie!)

  3. MemStatus.ullTotalVirtual oraz MemStatus.ullAvailVirtual, które powinny zwracać to co powyżej zwracają dziwne dane...

Proszę osoby obeznane z tematem o wytłumaczenie o co chodzi... Ja nie ogarniam :D

Dodam, że na Windows XP (32bit) są takie same cyrki.
A tak to wygląda:

ff.png

dodanie obrazka do treści posta - Furious Programming

3

Bo pole ullTotalVirtual i ullAvailVirtual tyczą się danego procesu, a nie całego systemu.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa366770(v=vs.85).aspx - Tutaj masz wyjaśnienie

0

@Anoxic
Masz rację z tym, że funkcja zwraca wartości dla procesu wywołującego. Ale, mimo to, moim zdaniem wciąż wartości: ullTotalPageFile, ullAvailPageFile oraz ullTotalVirtual, ullAvailVirtual są jakby na odwrót.
MSDN podaje, że aby pobrać wartości dla całego systemu, należy skorzystać z funkcji: GetPerformanceInfo.
OK, zatem oto nieco zmodyfikowany kod...

program Project1;

{$APPTYPE CONSOLE}

uses
  Windows,
  Classes,
  SysUtils;

type
  DWORDLONG = UInt64;

  PMemoryStatusEx = ^TMemoryStatusEx;
  TMemoryStatusEx = packed record
    dwLength: DWORD;
    dwMemoryLoad: DWORD;
    ullTotalPhys: DWORDLONG;
    ullAvailPhys: DWORDLONG;
    ullTotalPageFile: DWORDLONG;
    ullAvailPageFile: DWORDLONG;
    ullTotalVirtual: DWORDLONG;
    ullAvailVirtual: DWORDLONG;
    ullAvailExtendedVirtual: DWORDLONG;
  end;

function GlobalMemoryStatusEx(var lpBuffer: TMemoryStatusEx): BOOL; stdcall; external kernel32;

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 ;

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

procedure Main;
var
  MemStatus: TMemoryStatusEx;
  PerformanceInfo  : TPerformanceInformation ;
begin
  // initialize the structure
  FillChar(MemStatus, SizeOf(MemStatus), 0);
  MemStatus.dwLength := SizeOf(MemStatus);
  // check return code for errors
  Win32Check(GlobalMemoryStatusEx(MemStatus));

  Writeln(Format('Rozmiar (dwLength): x%d', [MemStatus.dwLength]));
  Writeln(Format('Pamiec uzywana (dwMemoryLoad): %d', [MemStatus.dwMemoryLoad]) + '%');

  // Physical Memory
  Writeln(Format('Calkowita Pamiec Fizyczna (ullTotalPhys): %f', [(MemStatus.ullTotalPhys /1024 /1024/1024)]) + ' GB');
  Writeln(Format('Dostepna Pamiec Fizyczna (ullAvailPhys): %f', [(MemStatus.ullAvailPhys /1024 /1024/1024)]) + ' GB');

  // Virtual Memory
  Writeln(Format('Calkowity Rozmiar Pliku Wymiany (ullTotalPageFile): %f', [MemStatus.ullTotalPageFile /1024 /1024/1024]) + ' GB');
  Writeln(Format('Dostepny Rozmiar Pliku Wymiany (ullAvailPageFile): %f', [MemStatus.ullAvailPageFile /1024 /1024/1024]) + ' GB');


  Writeln(Format('Calkowita Pamiec Wirtualna (ullTotalVirtual): %f', [MemStatus.ullTotalVirtual /1024 /1024/1024]) + ' GB');
  Writeln(Format('Dostepna Pamiec Wirtualna (ullAvailVirtual): %f', [MemStatus.ullAvailVirtual /1024 /1024/1024]) + ' GB');
  Writeln(Format('ullAvailExtendedVirtual: %d', [MemStatus.ullAvailExtendedVirtual]));

if (GetPerformanceInfo (Addr (PerformanceInfo), Sizeof (TPerformanceInformation)) <> 0) then
    begin
    with PerformanceInfo do
        begin
            Writeln(Format ('CommitTotal      : %u',[CommitTotal]));
            Writeln(Format ('CommitLimit      : %u',[CommitLimit]));
            Writeln(Format ('CommitPeak       : %u',[CommitPeak]));
            Writeln(Format ('PhysicalTotal    : %u',[PhysicalTotal]));
            Writeln(Format ('PhysicalAvailable: %u',[PhysicalAvailable]));


            Writeln(Format ('SystemCache      : %u',[SystemCache]));
            Writeln(Format ('KernelTotal      : %u',[KernelTotal]));
            Writeln(Format ('KernelPaged      : %u',[KernelPaged]));
            Writeln(Format ('KernelNonpaged   : %u',[KernelNonpaged]));
            Writeln(Format ('PageSize         : %u',[PageSize]));
            Writeln(Format ('HandleCount      : %u',[HandleCount])) ;
            Writeln(Format ('ProcessCount     : %u',[ProcessCount])) ;
            Writeln(Format ('ThreadCount      : %u',[ThreadCount])) ;


        end ;
    end ;
end;

begin
  try
    Main;
  except
    on E: Exception do
    begin
      ExitCode := 1;
      Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
    end;
  end;
end.

Wynik wykonania w załączniku...

I jak zinterpretować te wyniki? Jak to się ma do tego co podaje System (pierwszy post).
-Pawel

0

Jeśli zależy ci na informacjach o systemie proponuję skorzystać z WMI.
Tutaj masz przykład: http://stackoverflow.com/questions/2761328/how-do-i-use-wmi-with-delphi-without-drastically-increasing-the-applications-fi
A tu info na temat klasy Win32_OperatingSystem: http://msdn.microsoft.com/en-us/library/aa394239%28v=vs.85%29.aspx

0

Dzięki, niestety nie chcę korzystać z WMI w tym przypadku. Z WMI mam nawet spore doświadczenie. Jak ktoś jest zainteresowany, proszę oto mój programik, który rozwijam, oparty na WMI (jest jeszcze sporo do zrobienia, ale w zasadzie działa OK): http://www.pawelporwisz.pl/winamp/extra/WinampTools/SystemInformationTool/system_information_tool.php

Wracając do tematu. Robiłem testy z wykorzystaniem funkcji WMI, które odpalałem w wątku w bibliotece - korzystały z tego 2 programy - i nie działało to zbyt efektywnie (obciążenie procesora). Być może coś popsułem (mam wrażenie, że muszę jeszcze poczytać o bibliotece w wątku (a może tak się po prostu nie robi), ale czas mnie gonił.
Pozdrawiam,
-Pawel

1 użytkowników online, w tym zalogowanych: 0, gości: 1