GlobalMemoryStatusExを使用してシステムメモリの使用量を取得する方法を知っていますが、これにより、OS全体が使用しているものがわかります。
私は自分のプログラムに、それだけで割り当てられて使用しているメモリの量を報告してほしいです。
Delphi 2009プログラム内で、Windows関数またはFastMM関数を呼び出して、プログラムだけで割り当てられたメモリを見つける方法はありますか?
私の質問に戻り、@ apenwarrによって、受け入れられた回答をGetMemoryManagerState回答に変更しました。これは、以前使用していたGetHeapStatus関数(現在は非推奨)と同じ結果を生成しましたが、GetProcessMemoryInfo.WorkingSetSizeは非常に異なる結果を返しました。
Win32の直接呼び出しを使用せずに、Delphiランタイムから有用なメモリ使用情報を取得できます。
unit X;
uses FastMM4; //include this or method will return 0.
....
function GetMemoryUsed: UInt64;
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;
このメソッドの最も良い点は、厳密に追跡されることです。メモリを割り当てると増加し、メモリの割り当てを解除するとすぐに同じ量だけ減少します。私は、各ユニットテストの実行前と実行後にこれを使用しているため、たとえば、どのテストがメモリリークを起こしているのかわかります。
プログラムが使用しているメモリの量を知りたいですか?このDelphi関数でうまくいきます。
uses psAPI;
{...}
function CurrentProcessMemory: Cardinal;
var
MemCounters: TProcessMemoryCounters;
begin
MemCounters.cb := SizeOf(MemCounters);
if GetProcessMemoryInfo(GetCurrentProcess,
@MemCounters,
SizeOf(MemCounters)) then
Result := MemCounters.WorkingSetSize
else
RaiseLastOSError;
end;
私はこれの基本がどこにあるのかわからないが、いくつかのより良いエラー処理をそれに追加して、それを関数にした。 WorkingSetSizeは、現在使用されているメモリの量です。同様のコードを使用して、現在のプロセス(または任意のプロセス)の他の値を取得できます。 usesステートメントにpsAPIを含める必要があります。
PROCESS_MEMORY_COUNTERSレコードには以下が含まれます。
これらの値はすべて、タスクマネージャまたはプロセスエクスプローラで確認できます。
現在のプロセス(アプリ)のメモリ使用量を返すために、この小さな関数を書きました。
function ProcessMemory: longint;
var
pmc: PPROCESS_MEMORY_COUNTERS;
cb: Integer;
begin
// Get the used memory for the current process
cb := SizeOf(TProcessMemoryCounters);
GetMem(pmc, cb);
pmc^.cb := cb;
if GetProcessMemoryInfo(GetCurrentProcess(), pmc, cb) then
Result:= Longint(pmc^.WorkingSetSize);
FreeMem(pmc);
end;
SourceForgeから完全なFastMM4バンドルをダウンロードすると、デモに含まれているUsageTrackerDemoプロジェクトでFastMMを使用する方法の例を見ることができます。
Delphiのコンソールアプリケーションへの Gant C++コードの変換:
program MemoryProcessCMD;
{* Based in Gant(https://stackoverflow.com/users/12460/gant) code*}
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
psapi,
Windows;
procedure PrintMemoryInfo(processID: DWORD);
var
hProcess: THandle;
pmc: PROCESS_MEMORY_COUNTERS;
total: DWORD;
begin
// Print the process identifier.
Writeln(format('Process ID: %d', [processID]));
// Print information about the memory usage of the process.
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE,
processID);
if (hProcess = 0) then
begin
exit;
end;
if (GetProcessMemoryInfo(hProcess, @pmc, SizeOf(pmc))) then
begin
Writeln(format(#09'PageFaultCount: 0x%.8X', [pmc.PageFaultCount]));
Writeln(format(#09'PeakWorkingSetSize: 0x%.8X', [pmc.PeakWorkingSetSize]));
Writeln(format(#09'WorkingSetSize: 0x%.8X', [pmc.WorkingSetSize]));
Writeln(format(#09'QuotaPeakPagedPoolUsage: 0x%.8X',
[pmc.QuotaPeakPagedPoolUsage]));
Writeln(format(#09'QuotaPagedPoolUsage: 0x%.8X',
[pmc.QuotaPagedPoolUsage]));
Writeln(format(#09'QuotaPeakNonPagedPoolUsage: 0x%.8X',
[pmc.QuotaPeakNonPagedPoolUsage]));
Writeln(format(#09'QuotaNonPagedPoolUsage: 0x%.8X',
[pmc.QuotaNonPagedPoolUsage]));
Writeln(format(#09'PagefileUsage: 0x%.8X', [pmc.PagefileUsage]));
Writeln(format(#09'PeakPagefileUsage: 0x%.8X', [pmc.PeakPagefileUsage]));
Writeln(format(#09'PagefileUsage: 0x%.8X', [pmc.PagefileUsage]));
end;
CloseHandle(hProcess);
end;
var
aProcesses: array [0 .. 1024] of DWORD;
cbNeeded, cProcesses: DWORD;
i: Integer;
begin
try
// Get the list of process identifiers.
if (not EnumProcesses(@aProcesses, SizeOf(aProcesses), &cbNeeded)) then
halt(1);
// Calculate how many process identifiers were returned.
cProcesses := cbNeeded div SizeOf(DWORD);
// Print the memory usage for each process
for i := 0 to cProcesses - 1 do
begin
PrintMemoryInfo(aProcesses[i]);
end;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Win32 APIの方法では、GetProcessMemoryInfo関数が必要です。以下は MSDNページ の例ですが、コードはC++で記述されています。 Delphiにも変換できると思います。あなたが探しているものはおそらく「ワーキングセットサイズ」と呼ばれます。
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
void PrintMemoryInfo( DWORD processID )
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;
// Print the process identifier.
printf( "\nProcess ID: %u\n", processID );
// Print information about the memory usage of the process.
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if (NULL == hProcess)
return;
if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
printf( "\tPeakWorkingSetSize: 0x%08X\n",
pmc.PeakWorkingSetSize );
printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakPagedPoolUsage );
printf( "\tQuotaPagedPoolUsage: 0x%08X\n",
pmc.QuotaPagedPoolUsage );
printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakNonPagedPoolUsage );
printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaNonPagedPoolUsage );
printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
printf( "\tPeakPagefileUsage: 0x%08X\n",
pmc.PeakPagefileUsage );
}
CloseHandle( hProcess );
}
int main( )
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
return 1;
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the memory usage for each process
for ( i = 0; i < cProcesses; i++ )
PrintMemoryInfo( aProcesses[i] );
return 0;
}