Skip to content

Instantly share code, notes, and snippets.

@jpluimers
Last active November 7, 2018 06:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpluimers/b08b65991987d01e1dd1bdb4bf8a33c4 to your computer and use it in GitHub Desktop.
Save jpluimers/b08b65991987d01e1dd1bdb4bf8a33c4 to your computer and use it in GitHub Desktop.
Abstracting some non-UI logic from FastMMUsageTracker.pas into a separate unit.

MemoryManagerUnit.pas

This abstracts some non-UI logic from FastMMUsageTracker.pas.

Please shoot at it and the example.

I have implemented the .ToString methods using JSON, using extra classes because built-in Delphi JSON support has no easy way to convert a record to JSON and the base types (either in the System or FastMM4 unit) are record based.

There is some fiddling with record helpers so it works in FastMM and regular mode.

unit MemoryManagerUnit;
// based on ideas in https://stackoverflow.com/questions/437683/how-to-get-the-memory-used-by-a-delphi-program/437749
// and code from https://github.com/pleriche/FastMM4/blob/master/Demos/Usage%20Tracker/FastMMUsageTracker.pas
interface
uses
{$ifdef FastMM}
FastMM4,
{$endif FastMM}
Winapi.Windows;
type
TMemoryManagerStateHelper = record helper for TMemoryManagerState
function LargeBlockSizeUsageBytes: Cardinal;
function LogicalSmallBlockSizeUsageBytes: Cardinal;
function MediumBlockSizeUsageBytes: Cardinal;
function PysicalSmallBlockSizeUsageBytes: Cardinal;
function ReservedSmallBlockSizeUsageBytes: Cardinal;
function ReservedMemoryUsageBytes: Cardinal;
function TotalBlockSizeUsageBytes: Cardinal;
class function GetMemoryManagerState: TMemoryManagerState; static;
function ToString: string;
end;
TSmallBlockTypeStateHelper = record helper for TSmallBlockTypeState
function LogicalBlockSizeUsageBytes: Cardinal;
function PhysicalBlockSizeUsageBytes: Cardinal;
end;
{$ifndef FastMM}
{ From FastMM4.TMemoryManagerUsageSummary }
TMemoryManagerUsageSummary = record
{The total number of bytes allocated by the application.}
AllocatedBytes: NativeUInt;
{The total number of address space bytes used by control structures, or
lost due to fragmentation and other overhead.}
OverheadBytes: NativeUInt;
{The efficiency of the memory manager expressed as a percentage. This is
100 * AllocatedBytes / (AllocatedBytes + OverheadBytes).}
EfficiencyPercentage: Double;
class function GetMemoryManagerUsageSummary: TMemoryManagerUsageSummary; static;
end;
{$endif FastMM}
TMemoryManagerUsageSummaryHelper = record helper for TMemoryManagerUsageSummary
{$ifdef FastMM}
class function GetMemoryManagerUsageSummary: TMemoryManagerUsageSummary; static;
{$endif FastMM}
function ToString: string;
end;
// Various Windows API call results involving processor and memory state:
TWindowsProcessorAndMemoryStatus = record
ProcessorCount: DWORD;
AllocationGranularity: DWORD;
AvailablePhysicalMemory: Int64;
TotalPhysicalMemory: Int64;
AvailableVirtualMemory: Int64;
TotalVirtualMemory: Int64;
TotalVirtualExtendedMemory: Int64;
HaveTotalVirtualExtendedMemory: Boolean;
MaximumIncrement: ULONG;
PageSize: ULONG;
NumberOfPhysicalPages: ULONG;
LowestPhysicalPage: ULONG;
HighestPhysicalPage: ULONG;
HaveMaximumIncrement: Boolean;
HavePageSize: Boolean;
HaveNumberOfPhysicalPages: Boolean;
HaveLowestPhysicalPage: Boolean;
HaveHighestPhysicalPage: Boolean;
PageFaultCount: DWORD;
PeakWorkingSetSize: SIZE_T;
WorkingSetSize: SIZE_T;
QuotaPeakPagedPoolUsage: SIZE_T;
QuotaPagedPoolUsage: SIZE_T;
QuotaPeakNonPagedPoolUsage: SIZE_T;
QuotaNonPagedPoolUsage: SIZE_T;
PagefileUsage: SIZE_T;
PeakPagefileUsage: SIZE_T;
HavePageFaultCount: Boolean;
HavePeakWorkingSetSize: Boolean;
HaveWorkingSetSize: Boolean;
HaveQuotaPeakPagedPoolUsage: Boolean;
HaveQuotaPagedPoolUsage: Boolean;
HaveQuotaPeakNonPagedPoolUsage: Boolean;
HaveQuotaNonPagedPoolUsage: Boolean;
HavePagefileUsage: Boolean;
HavePeakPagefileUsage: Boolean;
CurrentProcessId: DWORD;
MinimumAddress: DWORD;
MaximumVMAddress: DWORD;
PageProtectionAndCommitSize: DWORD;
MinimumQuota: NativeUInt;
MaximumQuota: NativeUInt;
// TotalFree: DWord;
// TotalReserve: DWord;
// TotalCommit: DWord;
class function GetWindowsProcessorAndMemoryStatus: TWindowsProcessorAndMemoryStatus; static;
function ToString: string;
end;
implementation
uses
Winapi.PsAPI,
System.SysUtils,
REST.Json;
function ToJsonStringAndFree(const InstanceToFree: TObject): string;
begin
try
Result := TJson.ObjectToJsonString(InstanceToFree);
finally
InstanceToFree.Free();
end;
end;
{ Windows API calls from FastMMUsageTracker.pas: }
type
TMemoryStatusEx = packed record
dwLength: DWORD;
dwMemoryLoad: DWORD;
ullTotalPhys: Int64;
ullAvailPhys: Int64;
ullTotalPageFile: Int64;
ullAvailPageFile: Int64;
ullTotalVirtual: Int64;
ullAvailVirtual: Int64;
ullAvailExtendedVirtual: Int64;
end;
PMemoryStatusEx = ^TMemoryStatusEx;
LPMEMORYSTATUSEX = PMemoryStatusEx;
TP_GlobalMemoryStatusEx = function(var PR_MemStatusEx: TMemoryStatusEx): LongBool; stdcall;
TSystem_Basic_Information = packed record
dwUnknown1: DWORD;
uKeMaximumIncrement: ULONG;
uPageSize: ULONG;
uMmNumberOfPhysicalPages: ULONG;
uMmLowestPhysicalPage: ULONG;
uMmHighestPhysicalPage: ULONG;
uAllocationGranularity: ULONG;
pLowestUserAddress: Pointer;
pMmHighestUserAddress: Pointer;
uKeActiveProcessors: ULONG;
bKeNumberProcessors: Byte;
bUnknown2: Byte;
wUnknown3: Word;
end;
TSystem_Performance_Information = packed record
liIdleTime: LARGE_INTEGER;
dwSpare: array[0..75] of DWORD;
end;
TSystem_Time_Information = packed record
liKeBootTime: LARGE_INTEGER;
liKeSystemTime: LARGE_INTEGER;
liExpTimeZoneBias: LARGE_INTEGER;
uCurrentTimeZoneId: ULONG;
dwReserved: DWORD;
end;
TP_NtQuerySystemInformation = function(InfoClass: DWORD; Buffer: Pointer; BufSize: DWORD; ReturnSize: PCardinal): DWORD; stdcall;
var
MP_GlobalMemoryStatusEx: TP_GlobalMemoryStatusEx = nil;
MP_NtQuerySystemInformation: TP_NtQuerySystemInformation = nil;
{ Record helpers: }
function TMemoryManagerStateHelper.LargeBlockSizeUsageBytes: Cardinal;
begin
Result := TotalAllocatedLargeBlockSize * AllocatedLargeBlockCount;
end;
function TMemoryManagerStateHelper.LogicalSmallBlockSizeUsageBytes: Cardinal;
var
SmallBlockTypeState: TSmallBlockTypeState;
begin
Result := 0;
for SmallBlockTypeState in SmallBlockTypeStates do
begin
Inc(Result, SmallBlockTypeState.LogicalBlockSizeUsageBytes);
end;
end;
function TMemoryManagerStateHelper.MediumBlockSizeUsageBytes: Cardinal;
begin
Result := TotalAllocatedMediumBlockSize * AllocatedMediumBlockCount;
end;
function TMemoryManagerStateHelper.PysicalSmallBlockSizeUsageBytes: Cardinal;
var
SmallBlockTypeState: TSmallBlockTypeState;
begin
Result := 0;
for SmallBlockTypeState in SmallBlockTypeStates do
begin
Inc(Result, SmallBlockTypeState.PhysicalBlockSizeUsageBytes);
end;
end;
function TMemoryManagerStateHelper.ReservedSmallBlockSizeUsageBytes: Cardinal;
var
SmallBlockTypeState: TSmallBlockTypeState;
begin
Result := 0;
for SmallBlockTypeState in SmallBlockTypeStates do
begin
Inc(Result, SmallBlockTypeState.ReservedAddressSpace);
end;
end;
function TMemoryManagerStateHelper.ReservedMemoryUsageBytes: Cardinal;
begin
Result := ReservedMediumBlockAddressSpace + ReservedLargeBlockAddressSpace + ReservedSmallBlockSizeUsageBytes;
end;
{ Utility functions from FastMMUsageTracker.pas: }
function CardinalToStringFormatted(const ACardinal: Cardinal): string;
begin
Result := FormatFloat('#,##0', ACardinal);
end;
function Int64ToStringFormatted(const AInt64: Int64): string;
begin
Result := FormatFloat('#,##0', AInt64);
end;
function CardinalToKStringFormatted(const ACardinal: Cardinal): string;
begin
Result := FormatFloat('#,##0', ACardinal div 1024) + 'K';
end;
function Int64ToKStringFormatted(const AInt64: Int64): string;
begin
Result := FormatFloat('#,##0', AInt64 div 1024) + 'K';
end;
// REST.Json does not support converting records to JSON, so introduce an intermediate class
type
TMemoryManagerStateClass = class
LargeBlockSizeUsageBytes: Cardinal;
LogicalSmallBlockSizeUsageBytes: Cardinal;
MediumBlockSizeUsageBytes: Cardinal;
PysicalSmallBlockSizeUsageBytes: Cardinal;
ReservedSmallBlockSizeUsageBytes: Cardinal;
ReservedMemoryUsageBytes: Cardinal;
TotalBlockSizeUsageBytes: Cardinal;
public
constructor Create(const AMemoryManagerState: TMemoryManagerState);
end;
constructor TMemoryManagerStateClass.Create(const AMemoryManagerState: TMemoryManagerState);
begin
inherited Create();
LargeBlockSizeUsageBytes := AMemoryManagerState.LargeBlockSizeUsageBytes;
LogicalSmallBlockSizeUsageBytes := AMemoryManagerState.LogicalSmallBlockSizeUsageBytes;
MediumBlockSizeUsageBytes := AMemoryManagerState.MediumBlockSizeUsageBytes;
PysicalSmallBlockSizeUsageBytes := AMemoryManagerState.PysicalSmallBlockSizeUsageBytes;
ReservedSmallBlockSizeUsageBytes := AMemoryManagerState.ReservedSmallBlockSizeUsageBytes;
ReservedMemoryUsageBytes := AMemoryManagerState.ReservedMemoryUsageBytes;
TotalBlockSizeUsageBytes := AMemoryManagerState.TotalBlockSizeUsageBytes;
end;
class function TMemoryManagerStateHelper.GetMemoryManagerState: TMemoryManagerState;
begin
{$ifdef FastMM}
FastMM4
{$else}
System
{$endif FastMM}
.GetMemoryManagerState(Result);
end;
function TMemoryManagerStateHelper.ToString: string;
begin
Result := ToJsonStringAndFree(TMemoryManagerStateClass.Create(Self));
end;
function TMemoryManagerStateHelper.TotalBlockSizeUsageBytes: Cardinal;
begin
Result := TotalAllocatedMediumBlockSize + TotalAllocatedLargeBlockSize + PysicalSmallBlockSizeUsageBytes;
end;
function TSmallBlockTypeStateHelper.LogicalBlockSizeUsageBytes: Cardinal;
begin
Result := AllocatedBlockCount * InternalBlockSize;
end;
function TSmallBlockTypeStateHelper.PhysicalBlockSizeUsageBytes: Cardinal;
begin
Result := AllocatedBlockCount * UseableBlockSize;
end;
{$ifndef FastMM}
class function TMemoryManagerUsageSummary.GetMemoryManagerUsageSummary: TMemoryManagerUsageSummary;
var
LMMS: TMemoryManagerState;
LAllocatedBytes, LReservedBytes: NativeUInt;
begin
GetMemoryManagerState(LMMS);
LAllocatedBytes := LMMS.TotalBlockSizeUsageBytes;
LReservedBytes := LMMS.ReservedMemoryUsageBytes;
{Set the structure values}
Result.AllocatedBytes := LAllocatedBytes;
Result.OverheadBytes := LReservedBytes - LAllocatedBytes;
if LReservedBytes > 0 then
begin
Result.EfficiencyPercentage := LAllocatedBytes / LReservedBytes * 100;
end
else
Result.EfficiencyPercentage := 100;
end;
{$endif FastMM}
{$ifdef FastMM}
class function TMemoryManagerUsageSummaryHelper.GetMemoryManagerUsageSummary: TMemoryManagerUsageSummary;
begin
FastMM4.GetMemoryManagerUsageSummary(Result);
end;
{$endif FastMM}
// REST.Json does not support converting records to JSON, so introduce an intermediate class
type
TMemoryManagerUsageSummaryClass = class
AllocatedBytes: NativeUInt;
OverheadBytes: NativeUInt;
EfficiencyPercentage: Double;
public
constructor Create(const AMemoryManagerUsageSummary: TMemoryManagerUsageSummary);
end;
constructor TMemoryManagerUsageSummaryClass.Create(const AMemoryManagerUsageSummary: TMemoryManagerUsageSummary);
begin
inherited Create();
AllocatedBytes := AMemoryManagerUsageSummary.AllocatedBytes;
OverheadBytes := AMemoryManagerUsageSummary.OverheadBytes;
EfficiencyPercentage := AMemoryManagerUsageSummary.EfficiencyPercentage;
end;
function TMemoryManagerUsageSummaryHelper.ToString: string;
begin
Result := ToJsonStringAndFree(TMemoryManagerUsageSummaryClass.Create(Self));
end;
procedure ModuleInit;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
MP_GlobalMemoryStatusEx := TP_GlobalMemoryStatusEx(GetProcAddress(GetModuleHandle(kernel32), 'GlobalMemoryStatusEx'));
MP_NtQuerySystemInformation := TP_NtQuerySystemInformation(GetProcAddress(GetModuleHandle('ntdll.dll'), 'NtQuerySystemInformation'));
end;
end;
class function TWindowsProcessorAndMemoryStatus.GetWindowsProcessorAndMemoryStatus: TWindowsProcessorAndMemoryStatus;
const
SystemBasicInformation = 0;
var
LR_SystemInfo: TSystemInfo;
LR_GlobalMemoryStatus: TMemoryStatus;
LR_GlobalMemoryStatusEx: TMemoryStatusEx;
LR_ProcessMemoryCounters: TProcessMemoryCounters;
LR_SysBaseInfo: TSystem_Basic_Information;
LU_MinQuota: {$if CompilerVersion >= 23}NativeUInt{$else}Cardinal{$ifend};
LU_MaxQuota: {$if CompilerVersion >= 23}NativeUInt{$else}Cardinal{$ifend};
begin
LU_MinQuota := 0;
LU_MaxQuota := 0;
if Assigned(MP_GlobalMemoryStatusEx) then
begin
ZeroMemory(@LR_GlobalMemoryStatusEx, SizeOf(TMemoryStatusEx));
LR_GlobalMemoryStatusEx.dwLength := SizeOf(TMemoryStatusEx);
if not MP_GlobalMemoryStatusEx(LR_GlobalMemoryStatusEx) then
begin
RaiseLastOSError();
end;
end
else
begin
LR_GlobalMemoryStatus.dwLength := SizeOf(TMemoryStatus);
GlobalMemoryStatus(LR_GlobalMemoryStatus);
end;
GetProcessWorkingSetSize(GetCurrentProcess, LU_MinQuota, LU_MaxQuota);
GetSystemInfo(LR_SystemInfo);
Result.ProcessorCount := LR_SystemInfo.dwNumberOfProcessors;
Result.AllocationGranularity := LR_SystemInfo.dwAllocationGranularity;
Result.MinimumAddress := DWORD(LR_SystemInfo.lpMinimumApplicationAddress);
Result.MaximumVMAddress := DWORD(LR_SystemInfo.lpMaximumApplicationAddress);
Result.PageProtectionAndCommitSize := LR_SystemInfo.dWPageSize;
if Assigned(MP_GlobalMemoryStatusEx) then
begin
with LR_GlobalMemoryStatusEx do
begin
Result.AvailablePhysicalMemory := LR_GlobalMemoryStatusEx.ullAvailPhys;
Result.TotalPhysicalMemory := LR_GlobalMemoryStatusEx.ullTotalPhys;
Result.AvailableVirtualMemory := LR_GlobalMemoryStatusEx.ullAvailVirtual;
Result.TotalVirtualMemory := LR_GlobalMemoryStatusEx.ullTotalVirtual;
Result.TotalVirtualExtendedMemory := LR_GlobalMemoryStatusEx.ullAvailExtendedVirtual;
Result.HaveTotalVirtualExtendedMemory := True;
end;
end
else
begin
with LR_GlobalMemoryStatus do
begin
Result.AvailablePhysicalMemory := LR_GlobalMemoryStatus.dwAvailPhys;
Result.TotalPhysicalMemory := LR_GlobalMemoryStatus.dwTotalPhys;
Result.AvailableVirtualMemory := LR_GlobalMemoryStatus.dwAvailVirtual;
Result.TotalVirtualMemory := LR_GlobalMemoryStatus.dwTotalVirtual;
Result.TotalVirtualExtendedMemory := -1;
Result.HaveTotalVirtualExtendedMemory := False;
end;
end;
if Assigned(MP_NtQuerySystemInformation) and
(0 = MP_NtQuerySystemInformation(SystemBasicInformation, @LR_SysBaseInfo, SizeOf(LR_SysBaseInfo), nil))
then
begin
Result.MaximumIncrement := LR_SysBaseInfo.uKeMaximumIncrement;
Result.PageSize := LR_SysBaseInfo.uPageSize;
Result.NumberOfPhysicalPages := LR_SysBaseInfo.uMmNumberOfPhysicalPages;
Result.LowestPhysicalPage := LR_SysBaseInfo.uMmLowestPhysicalPage;
Result.HighestPhysicalPage := LR_SysBaseInfo.uMmHighestPhysicalPage;
Result.HaveMaximumIncrement := True;
Result.HavePageSize := True;
Result.HaveNumberOfPhysicalPages := True;
Result.HaveLowestPhysicalPage := True;
Result.HaveHighestPhysicalPage := True;
end
else
begin
Result.MaximumIncrement := 0;
Result.PageSize := 0;
Result.NumberOfPhysicalPages := 0;
Result.LowestPhysicalPage := 0;
Result.HighestPhysicalPage := 0;
Result.HaveMaximumIncrement := False;
Result.HavePageSize := False;
Result.HaveNumberOfPhysicalPages := False;
Result.HaveLowestPhysicalPage := False;
Result.HaveHighestPhysicalPage := False;
end;
// same as GetProcessMemoryInfo & NtQuerySystemInformation (SystemBasicInformation
// The working set is the amount of memory physically mapped to the process context at a given
// time. Memory in the paged pool is system memory that can be transferred to the paging file
// on disk (paged) when it is not being used. Memory in the nonpaged pool is system memory
// that cannot be paged to disk as long as the corresponding objects are allocated. The pagefile
// usage represents how much memory is set aside for the process in the system paging file.
// When memory usage is too high, the virtual memory manager pages selected memory to disk.
// When a thread needs a page that is not in memory, the memory manager reloads it from the
// paging file.
if GetProcessMemoryInfo(GetCurrentProcess, @LR_ProcessMemoryCounters, SizeOf(LR_ProcessMemoryCounters)) then
begin
Result.PageFaultCount := LR_ProcessMemoryCounters.PageFaultCount;
Result.PeakWorkingSetSize := LR_ProcessMemoryCounters.PeakWorkingSetSize;
Result.WorkingSetSize := LR_ProcessMemoryCounters.WorkingSetSize;
Result.QuotaPeakPagedPoolUsage := LR_ProcessMemoryCounters.QuotaPeakPagedPoolUsage;
Result.QuotaPagedPoolUsage := LR_ProcessMemoryCounters.QuotaPagedPoolUsage;
Result.QuotaPeakNonPagedPoolUsage := LR_ProcessMemoryCounters.QuotaPeakNonPagedPoolUsage;
Result.QuotaNonPagedPoolUsage := LR_ProcessMemoryCounters.QuotaNonPagedPoolUsage;
Result.PagefileUsage := LR_ProcessMemoryCounters.PagefileUsage;
Result.PeakPagefileUsage := LR_ProcessMemoryCounters.PeakPagefileUsage;
Result.HavePageFaultCount := True;
Result.HavePeakWorkingSetSize := True;
Result.HaveWorkingSetSize := True;
Result.HaveQuotaPeakPagedPoolUsage := True;
Result.HaveQuotaPagedPoolUsage := True;
Result.HaveQuotaPeakNonPagedPoolUsage := True;
Result.HaveQuotaNonPagedPoolUsage := True;
Result.HavePagefileUsage := True;
Result.HavePeakPagefileUsage := True;
end
else
begin
Result.PageFaultCount := 0;
Result.PeakWorkingSetSize := 0;
Result.WorkingSetSize := 0;
Result.QuotaPeakPagedPoolUsage := 0;
Result.QuotaPagedPoolUsage := 0;
Result.QuotaPeakNonPagedPoolUsage := 0;
Result.QuotaNonPagedPoolUsage := 0;
Result.PagefileUsage := 0;
Result.PeakPagefileUsage := 0;
Result.HavePageFaultCount := False;
Result.HavePeakWorkingSetSize := False;
Result.HaveWorkingSetSize := False;
Result.HaveQuotaPeakPagedPoolUsage := False;
Result.HaveQuotaPagedPoolUsage := False;
Result.HaveQuotaPeakNonPagedPoolUsage := False;
Result.HaveQuotaNonPagedPoolUsage := False;
Result.HavePagefileUsage := False;
Result.HavePeakPagefileUsage := False;
end;
Result.CurrentProcessId := GetCurrentProcessId();
Result.MinimumQuota := LU_MinQuota;
Result.MaximumQuota := LU_MaxQuota;
{TODO -oJWP -cEnhancement : Future }
// Result.TotalFree := LU_MEM_FREE;
// Result.TotalReserve := LU_MEM_RESERVE;
// Result.TotalCommit := LU_MEM_COMMIT;
// if LP_FreeVMList.Count > CI_MaxFreeBlocksList then
// LI_Max := CI_MaxFreeBlocksList - 1
// else
// LI_Max := LP_FreeVMList.Count - 1;
//
// for LI_I := 0 to LI_Max do
// begin
// Result.Largest Free Block ' + IntToStr(LI_I + 1) + '. = ' + CardinalToKStringFormatted(Cardinal(LP_Free:= LI_I]);
// end;
// In case we want to add a FastMM4 summary:
// Result.TotalBlocks := LTotalBlocks;
// Result.TotalAllocated := LTotalAllocated;
// Result.TotalReserved := LTotalReserved;
end;
// REST.Json does not support converting records to JSON, so introduce an intermediate class
type
TWindowsProcessorAndMemoryStatusClass = class
ProcessorCount: DWORD;
AllocationGranularity: DWORD;
AvailablePhysicalMemory: Int64;
TotalPhysicalMemory: Int64;
AvailableVirtualMemory: Int64;
TotalVirtualMemory: Int64;
TotalVirtualExtendedMemory: Int64;
HaveTotalVirtualExtendedMemory: Boolean;
MaximumIncrement: ULONG;
PageSize: ULONG;
NumberOfPhysicalPages: ULONG;
LowestPhysicalPage: ULONG;
HighestPhysicalPage: ULONG;
HaveMaximumIncrement: Boolean;
HavePageSize: Boolean;
HaveNumberOfPhysicalPages: Boolean;
HaveLowestPhysicalPage: Boolean;
HaveHighestPhysicalPage: Boolean;
PageFaultCount: DWORD;
PeakWorkingSetSize: SIZE_T;
WorkingSetSize: SIZE_T;
QuotaPeakPagedPoolUsage: SIZE_T;
QuotaPagedPoolUsage: SIZE_T;
QuotaPeakNonPagedPoolUsage: SIZE_T;
QuotaNonPagedPoolUsage: SIZE_T;
PagefileUsage: SIZE_T;
PeakPagefileUsage: SIZE_T;
HavePageFaultCount: Boolean;
HavePeakWorkingSetSize: Boolean;
HaveWorkingSetSize: Boolean;
HaveQuotaPeakPagedPoolUsage: Boolean;
HaveQuotaPagedPoolUsage: Boolean;
HaveQuotaPeakNonPagedPoolUsage: Boolean;
HaveQuotaNonPagedPoolUsage: Boolean;
HavePagefileUsage: Boolean;
HavePeakPagefileUsage: Boolean;
CurrentProcessId: DWORD;
MinimumAddress: DWORD;
MaximumVMAddress: DWORD;
PageProtectionAndCommitSize: DWORD;
MinimumQuota: NativeUInt;
MaximumQuota: NativeUInt;
// TotalFree: DWord;
// TotalReserve: DWord;
// TotalCommit: DWord;
public
constructor Create(const AWindowsProcessorAndMemoryStatus: TWindowsProcessorAndMemoryStatus);
end;
constructor TWindowsProcessorAndMemoryStatusClass.Create(const AWindowsProcessorAndMemoryStatus:
TWindowsProcessorAndMemoryStatus);
begin
inherited Create();
ProcessorCount := AWindowsProcessorAndMemoryStatus.ProcessorCount;
AllocationGranularity := AWindowsProcessorAndMemoryStatus.AllocationGranularity;
AvailablePhysicalMemory := AWindowsProcessorAndMemoryStatus.AvailablePhysicalMemory;
TotalPhysicalMemory := AWindowsProcessorAndMemoryStatus.TotalPhysicalMemory;
AvailableVirtualMemory := AWindowsProcessorAndMemoryStatus.AvailableVirtualMemory;
TotalVirtualMemory := AWindowsProcessorAndMemoryStatus.TotalVirtualMemory;
TotalVirtualExtendedMemory := AWindowsProcessorAndMemoryStatus.TotalVirtualExtendedMemory;
HaveTotalVirtualExtendedMemory := AWindowsProcessorAndMemoryStatus.HaveTotalVirtualExtendedMemory;
MaximumIncrement := AWindowsProcessorAndMemoryStatus.MaximumIncrement;
PageSize := AWindowsProcessorAndMemoryStatus.PageSize;
NumberOfPhysicalPages := AWindowsProcessorAndMemoryStatus.NumberOfPhysicalPages;
LowestPhysicalPage := AWindowsProcessorAndMemoryStatus.LowestPhysicalPage;
HighestPhysicalPage := AWindowsProcessorAndMemoryStatus.HighestPhysicalPage;
HaveMaximumIncrement := AWindowsProcessorAndMemoryStatus.HaveMaximumIncrement;
HavePageSize := AWindowsProcessorAndMemoryStatus.HavePageSize;
HaveNumberOfPhysicalPages := AWindowsProcessorAndMemoryStatus.HaveNumberOfPhysicalPages;
HaveLowestPhysicalPage := AWindowsProcessorAndMemoryStatus.HaveLowestPhysicalPage;
HaveHighestPhysicalPage := AWindowsProcessorAndMemoryStatus.HaveHighestPhysicalPage;
PageFaultCount := AWindowsProcessorAndMemoryStatus.PageFaultCount;
PeakWorkingSetSize := AWindowsProcessorAndMemoryStatus.PeakWorkingSetSize;
WorkingSetSize := AWindowsProcessorAndMemoryStatus.WorkingSetSize;
QuotaPeakPagedPoolUsage := AWindowsProcessorAndMemoryStatus.QuotaPeakPagedPoolUsage;
QuotaPagedPoolUsage := AWindowsProcessorAndMemoryStatus.QuotaPagedPoolUsage;
QuotaPeakNonPagedPoolUsage := AWindowsProcessorAndMemoryStatus.QuotaPeakNonPagedPoolUsage;
QuotaNonPagedPoolUsage := AWindowsProcessorAndMemoryStatus.QuotaNonPagedPoolUsage;
PagefileUsage := AWindowsProcessorAndMemoryStatus.PagefileUsage;
PeakPagefileUsage := AWindowsProcessorAndMemoryStatus.PeakPagefileUsage;
HavePageFaultCount := AWindowsProcessorAndMemoryStatus.HavePageFaultCount;
HavePeakWorkingSetSize := AWindowsProcessorAndMemoryStatus.HavePeakWorkingSetSize;
HaveWorkingSetSize := AWindowsProcessorAndMemoryStatus.HaveWorkingSetSize;
HaveQuotaPeakPagedPoolUsage := AWindowsProcessorAndMemoryStatus.HaveQuotaPeakPagedPoolUsage;
HaveQuotaPagedPoolUsage := AWindowsProcessorAndMemoryStatus.HaveQuotaPagedPoolUsage;
HaveQuotaPeakNonPagedPoolUsage := AWindowsProcessorAndMemoryStatus.HaveQuotaPeakNonPagedPoolUsage;
HaveQuotaNonPagedPoolUsage := AWindowsProcessorAndMemoryStatus.HaveQuotaNonPagedPoolUsage;
HavePagefileUsage := AWindowsProcessorAndMemoryStatus.HavePagefileUsage;
HavePeakPagefileUsage := AWindowsProcessorAndMemoryStatus.HavePeakPagefileUsage;
CurrentProcessId := AWindowsProcessorAndMemoryStatus.CurrentProcessId;
MinimumAddress := AWindowsProcessorAndMemoryStatus.MinimumAddress;
MaximumVMAddress := AWindowsProcessorAndMemoryStatus.MaximumVMAddress;
PageProtectionAndCommitSize := AWindowsProcessorAndMemoryStatus.PageProtectionAndCommitSize;
MinimumQuota := AWindowsProcessorAndMemoryStatus.MinimumQuota;
MaximumQuota := AWindowsProcessorAndMemoryStatus.MaximumQuota;
end;
function TWindowsProcessorAndMemoryStatus.ToString: string;
begin
Result := ToJsonStringAndFree(TWindowsProcessorAndMemoryStatusClass.Create(Self));
end;
initialization
ModuleInit;
end.
unit UsageUnit;
interface
procedure WriteProcessorAndMemoryInfoToConsole();
implementation
uses
{$ifdef FastMM}
FastMM4,
{$endif FastMM}
System.SysUtils,
MemoryManagerUnit;
procedure WriteProcessorAndMemoryInfoToConsole();
begin
Writeln(Format('Memory manager summary: %s', [TMemoryManagerUsageSummary.GetMemoryManagerUsageSummary().ToString()]));
Writeln(Format('Memory manager state: %s', [TMemoryManagerState.GetMemoryManagerState().ToString()]));
Writeln(Format('Windows process and memory state: %s.', [TWindowsProcessorAndMemoryStatus.GetWindowsProcessorAndMemoryStatus().ToString()]));
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment