@@ -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