Skip to content

Commit 624f7cb

Browse files
committed
feat: Improve memory statistics for CPU and GPU
1 parent 4cb974f commit 624f7cb

File tree

1 file changed

+93
-8
lines changed

1 file changed

+93
-8
lines changed

Source/RunActivity/Viewer3D/Popups/HUDWindow.cs

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,29 @@ public class HUDWindow : LayeredWindow
4848

4949
readonly int ProcessorCount = System.Environment.ProcessorCount;
5050

51-
readonly PerformanceCounter AllocatedBytesPerSecCounter; // \.NET CLR Memory(*)\Allocated Bytes/sec
52-
float AllocatedBytesPerSecLastValue;
51+
const int PerformanceCounterUpdateTimeS = 10;
52+
float PerformanceCounterElapsedTimeS;
53+
54+
readonly PerformanceCounter CLRMemoryAllocatedBytesPerSecCounter; // \.NET CLR Memory(*)\Allocated Bytes/sec
55+
float CLRMemoryAllocatedBytesPerSec;
56+
57+
readonly PerformanceCounter CPUMemoryPrivateCounter; // \Process(*)\Private Bytes
58+
readonly PerformanceCounter CPUMemoryWorkingSetCounter; // \Process(*)\Working Set
59+
readonly PerformanceCounter CPUMemoryWorkingSetPrivateCounter; // \Process(*)\Working Set - Private
60+
readonly PerformanceCounter CPUMemoryVirtualCounter; // \Process(*)\Virtual Bytes
61+
62+
float CPUMemoryPrivate;
63+
float CPUMemoryWorkingSet;
64+
float CPUMemoryWorkingSetPrivate;
65+
float CPUMemoryVirtual;
66+
67+
readonly List<PerformanceCounter> GPUMemoryCommittedCounters = new List<PerformanceCounter>(); // \GPU Process Memory(*)\Total Committed
68+
readonly List<PerformanceCounter> GPUMemoryDedicatedCounters = new List<PerformanceCounter>(); // \GPU Process Memory(*)\Dedicated Usage
69+
readonly List<PerformanceCounter> GPUMemorySharedCounters = new List<PerformanceCounter>(); // \GPU Process Memory(*)\Shared Usage
70+
71+
float GPUMemoryCommitted;
72+
float GPUMemoryDedicated;
73+
float GPUMemoryShared;
5374

5475
readonly Viewer Viewer;
5576
readonly Action<TableData>[] TextPages;
@@ -98,7 +119,8 @@ public HUDWindow(WindowManager owner)
98119
var processId = new PerformanceCounter(".NET CLR Memory", "Process ID", process);
99120
if (processId.NextValue() == Process.GetCurrentProcess().Id)
100121
{
101-
AllocatedBytesPerSecCounter = new PerformanceCounter(".NET CLR Memory", "Allocated Bytes/sec", process);
122+
CLRMemoryAllocatedBytesPerSecCounter = new PerformanceCounter(".NET CLR Memory", "Allocated Bytes/sec", process);
123+
Trace.TraceInformation($"Found Microsoft .NET Framework performance counter {process}");
102124
break;
103125
}
104126
}
@@ -109,6 +131,50 @@ public HUDWindow(WindowManager owner)
109131
Trace.TraceWarning("Unable to access Microsoft .NET Framework performance counters. This may be resolved by following the instructions at http://support.microsoft.com/kb/300956");
110132
}
111133

134+
try
135+
{
136+
var counterProcess = new PerformanceCounterCategory("Process");
137+
foreach (var process in counterProcess.GetInstanceNames())
138+
{
139+
var processId = new PerformanceCounter("Process", "ID Process", process);
140+
if (processId.NextValue() == Process.GetCurrentProcess().Id)
141+
{
142+
CPUMemoryPrivateCounter = new PerformanceCounter("Process", "Private Bytes", process);
143+
CPUMemoryWorkingSetCounter = new PerformanceCounter("Process", "Working Set", process);
144+
CPUMemoryWorkingSetPrivateCounter = new PerformanceCounter("Process", "Working Set - Private", process);
145+
CPUMemoryVirtualCounter = new PerformanceCounter("Process", "Virtual Bytes", process);
146+
Trace.TraceInformation($"Found Windows Process performance counter {process}");
147+
break;
148+
}
149+
}
150+
}
151+
catch (Exception error)
152+
{
153+
Trace.WriteLine(error);
154+
Trace.TraceWarning("Unable to access Windows Process performance counters. This may be resolved by following the instructions at http://support.microsoft.com/kb/300956");
155+
}
156+
157+
try
158+
{
159+
var instancePrefix = $"pid_{Process.GetCurrentProcess().Id}_";
160+
var counterProcess = new PerformanceCounterCategory("GPU Process Memory");
161+
foreach (var process in counterProcess.GetInstanceNames())
162+
{
163+
if (process.StartsWith(instancePrefix))
164+
{
165+
GPUMemoryCommittedCounters.Add(new PerformanceCounter("GPU Process Memory", "Total Committed", process));
166+
GPUMemoryDedicatedCounters.Add(new PerformanceCounter("GPU Process Memory", "Dedicated Usage", process));
167+
GPUMemorySharedCounters.Add(new PerformanceCounter("GPU Process Memory", "Shared Usage", process));
168+
Trace.TraceInformation($"Found Windows GPU Process Memory performance counter {process}");
169+
}
170+
}
171+
}
172+
catch (Exception error)
173+
{
174+
Trace.WriteLine(error);
175+
Trace.TraceWarning("Unable to access Windows GPU Process Memory performance counters. This may be resolved by following the instructions at http://support.microsoft.com/kb/300956");
176+
}
177+
112178
Debug.Assert(GC.MaxGeneration == 2, "Runtime is expected to have a MaxGeneration of 2.");
113179

114180
var textPages = new List<Action<TableData>>();
@@ -257,6 +323,13 @@ public override void PrepareFrame(ElapsedTime elapsedTime, bool updateFull)
257323
{
258324
base.PrepareFrame(elapsedTime, updateFull);
259325

326+
PerformanceCounterElapsedTimeS += elapsedTime.RealSeconds;
327+
if (PerformanceCounterElapsedTimeS >= PerformanceCounterUpdateTimeS)
328+
{
329+
UpdatePerformanceCounters();
330+
PerformanceCounterElapsedTimeS = 0;
331+
}
332+
260333
if (updateFull)
261334
{
262335
var table = new TableData() { Cells = new string[TextTable.Cells.GetLength(0), TextTable.Cells.GetLength(1)] };
@@ -1304,15 +1377,13 @@ void TextPageDebugInfo(TableData table)
13041377
TableSetLabelValueColumns(table, 0, 2);
13051378
TextPageHeading(table, Viewer.Catalog.GetString("DEBUG INFORMATION"));
13061379

1307-
var allocatedBytesPerSecond = AllocatedBytesPerSecCounter == null ? 0 : AllocatedBytesPerSecCounter.NextValue();
1308-
if (allocatedBytesPerSecond >= 1 && AllocatedBytesPerSecLastValue != allocatedBytesPerSecond)
1309-
AllocatedBytesPerSecLastValue = allocatedBytesPerSecond;
1310-
13111380
TableAddLabelValue(table, Viewer.Catalog.GetString("Logging enabled"), Viewer.Settings.DataLogger ? Viewer.Catalog.GetString("Yes") : Viewer.Catalog.GetString("No"));
13121381
TableAddLabelValue(table, Viewer.Catalog.GetString("Build"), VersionInfo.Build);
1313-
TableAddLabelValue(table, Viewer.Catalog.GetString("Memory"), Viewer.Catalog.GetStringFmt("{0:F0} MB ({5}, {6}, {7}, {8}, {1:F0} MB managed, {9:F0} kB/frame allocated, {2:F0}/{3:F0}/{4:F0} GCs)", GetWorkingSetSize() / 1024 / 1024, GC.GetTotalMemory(false) / 1024 / 1024, GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), Viewer.TextureManager.GetStatus(), Viewer.MaterialManager.GetStatus(), Viewer.ShapeManager.GetStatus(), Viewer.World.Terrain.GetStatus(), AllocatedBytesPerSecLastValue / Viewer.RenderProcess.FrameRate.SmoothedValue / 1024));
13141382
TableAddLabelValue(table, Viewer.Catalog.GetString("CPU"), Viewer.Catalog.GetStringFmt("{0:F0}% ({1})", (Viewer.RenderProcess.Profiler.CPU.SmoothedValue + Viewer.UpdaterProcess.Profiler.CPU.SmoothedValue + Viewer.LoaderProcess.Profiler.CPU.SmoothedValue + Viewer.SoundProcess.Profiler.CPU.SmoothedValue) / ProcessorCount, Viewer.Catalog.GetPluralStringFmt("{0} logical processor", "{0} logical processors", ProcessorCount)));
13151383
TableAddLabelValue(table, Viewer.Catalog.GetString("GPU"), Viewer.Catalog.GetStringFmt("{0:F0} FPS (50th/95th/99th percentiles {1:F1} / {2:F1} / {3:F1} ms, DirectX feature level >= {4})", Viewer.RenderProcess.FrameRate.SmoothedValue, Viewer.RenderProcess.FrameTime.SmoothedP50 * 1000, Viewer.RenderProcess.FrameTime.SmoothedP95 * 1000, Viewer.RenderProcess.FrameTime.SmoothedP99 * 1000, Viewer.Settings.DirectXFeatureLevel));
1384+
TableAddLabelValue(table, Viewer.Catalog.GetString("Memory"), Viewer.Catalog.GetStringFmt("{3}, {4}, {5}, {6} ({7:F0} kB/frame allocated, {0:F0}/{1:F0}/{2:F0} GCs)", GC.CollectionCount(0), GC.CollectionCount(1), GC.CollectionCount(2), Viewer.TextureManager.GetStatus(), Viewer.MaterialManager.GetStatus(), Viewer.ShapeManager.GetStatus(), Viewer.World.Terrain.GetStatus(), CLRMemoryAllocatedBytesPerSec / Viewer.RenderProcess.FrameRate.SmoothedValue / 1024));
1385+
TableAddLabelValue(table, Viewer.Catalog.GetString("CPU Memory"), Viewer.Catalog.GetStringFmt("{0:F0} MB private, {1:F0} MB working set, {2:F0} MB private working set, {3:F0} MB managed, {4:F0} MB virtual", CPUMemoryPrivate / 1024 / 1024, CPUMemoryWorkingSet / 1024 / 1024, CPUMemoryWorkingSetPrivate / 1024 / 1024, GC.GetTotalMemory(false) / 1024 / 1024, CPUMemoryVirtual / 1024 / 1024));
1386+
TableAddLabelValue(table, Viewer.Catalog.GetString("GPU Memory"), Viewer.Catalog.GetStringFmt("{0:F0} MB committed, {1:F0} MB dedicated, {2:F0} MB shared", GPUMemoryCommitted / 1024 / 1024, GPUMemoryDedicated / 1024 / 1024, GPUMemoryShared / 1024 / 1024));
13161387
TableAddLabelValue(table, Viewer.Catalog.GetString("Adapter"), Viewer.Catalog.GetStringFmt("{0} ({1:F0} MB)", Viewer.AdapterDescription, Viewer.AdapterMemory / 1024 / 1024));
13171388
if (Viewer.Settings.DynamicShadows)
13181389
{
@@ -1396,6 +1467,20 @@ public ulong GetVirtualAddressLimit()
13961467
GlobalMemoryStatusEx(buffer);
13971468
return Math.Min(buffer.TotalVirtual, buffer.TotalPhysical);
13981469
}
1470+
1471+
void UpdatePerformanceCounters()
1472+
{
1473+
// Only update CLRMemoryAllocatedBytesPerSec with non-zero values
1474+
var clrMemoryAllocatedBytesPerSec = CLRMemoryAllocatedBytesPerSecCounter?.NextValue() ?? 0;
1475+
if (clrMemoryAllocatedBytesPerSec >= 1) CLRMemoryAllocatedBytesPerSec = clrMemoryAllocatedBytesPerSec;
1476+
CPUMemoryPrivate = CPUMemoryPrivateCounter?.NextValue() ?? 0;
1477+
CPUMemoryWorkingSet = CPUMemoryWorkingSetCounter?.NextValue() ?? 0;
1478+
CPUMemoryWorkingSetPrivate = CPUMemoryWorkingSetPrivateCounter?.NextValue() ?? 0;
1479+
CPUMemoryVirtual = CPUMemoryVirtualCounter?.NextValue() ?? 0;
1480+
GPUMemoryCommitted = GPUMemoryCommittedCounters.Sum(counter => counter.NextValue());
1481+
GPUMemoryDedicated = GPUMemoryDedicatedCounters.Sum(counter => counter.NextValue());
1482+
GPUMemoryShared = GPUMemorySharedCounters.Sum(counter => counter.NextValue());
1483+
}
13991484
}
14001485

14011486
public class HUDGraphSet

0 commit comments

Comments
 (0)