@@ -48,8 +48,29 @@ public class HUDWindow : LayeredWindow
48
48
49
49
readonly int ProcessorCount = System . Environment . ProcessorCount ;
50
50
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 ;
53
74
54
75
readonly Viewer Viewer ;
55
76
readonly Action < TableData > [ ] TextPages ;
@@ -98,7 +119,8 @@ public HUDWindow(WindowManager owner)
98
119
var processId = new PerformanceCounter ( ".NET CLR Memory" , "Process ID" , process ) ;
99
120
if ( processId . NextValue ( ) == Process . GetCurrentProcess ( ) . Id )
100
121
{
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 } ") ;
102
124
break ;
103
125
}
104
126
}
@@ -109,6 +131,50 @@ public HUDWindow(WindowManager owner)
109
131
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" ) ;
110
132
}
111
133
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
+
112
178
Debug . Assert ( GC . MaxGeneration == 2 , "Runtime is expected to have a MaxGeneration of 2." ) ;
113
179
114
180
var textPages = new List < Action < TableData > > ( ) ;
@@ -257,6 +323,13 @@ public override void PrepareFrame(ElapsedTime elapsedTime, bool updateFull)
257
323
{
258
324
base . PrepareFrame ( elapsedTime , updateFull ) ;
259
325
326
+ PerformanceCounterElapsedTimeS += elapsedTime . RealSeconds ;
327
+ if ( PerformanceCounterElapsedTimeS >= PerformanceCounterUpdateTimeS )
328
+ {
329
+ UpdatePerformanceCounters ( ) ;
330
+ PerformanceCounterElapsedTimeS = 0 ;
331
+ }
332
+
260
333
if ( updateFull )
261
334
{
262
335
var table = new TableData ( ) { Cells = new string [ TextTable . Cells . GetLength ( 0 ) , TextTable . Cells . GetLength ( 1 ) ] } ;
@@ -1304,15 +1377,13 @@ void TextPageDebugInfo(TableData table)
1304
1377
TableSetLabelValueColumns ( table , 0 , 2 ) ;
1305
1378
TextPageHeading ( table , Viewer . Catalog . GetString ( "DEBUG INFORMATION" ) ) ;
1306
1379
1307
- var allocatedBytesPerSecond = AllocatedBytesPerSecCounter == null ? 0 : AllocatedBytesPerSecCounter . NextValue ( ) ;
1308
- if ( allocatedBytesPerSecond >= 1 && AllocatedBytesPerSecLastValue != allocatedBytesPerSecond )
1309
- AllocatedBytesPerSecLastValue = allocatedBytesPerSecond ;
1310
-
1311
1380
TableAddLabelValue ( table , Viewer . Catalog . GetString ( "Logging enabled" ) , Viewer . Settings . DataLogger ? Viewer . Catalog . GetString ( "Yes" ) : Viewer . Catalog . GetString ( "No" ) ) ;
1312
1381
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 ) ) ;
1314
1382
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 ) ) ) ;
1315
1383
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 ) ) ;
1316
1387
TableAddLabelValue ( table , Viewer . Catalog . GetString ( "Adapter" ) , Viewer . Catalog . GetStringFmt ( "{0} ({1:F0} MB)" , Viewer . AdapterDescription , Viewer . AdapterMemory / 1024 / 1024 ) ) ;
1317
1388
if ( Viewer . Settings . DynamicShadows )
1318
1389
{
@@ -1396,6 +1467,20 @@ public ulong GetVirtualAddressLimit()
1396
1467
GlobalMemoryStatusEx ( buffer ) ;
1397
1468
return Math . Min ( buffer . TotalVirtual , buffer . TotalPhysical ) ;
1398
1469
}
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
+ }
1399
1484
}
1400
1485
1401
1486
public class HUDGraphSet
0 commit comments