1- using System . Collections . Generic ;
1+ using System ;
22using Improbable . Gdk . Core ;
3+ using Improbable . Worker ;
34using Improbable . Worker . Core ;
45using Unity . Entities ;
56using UnityEngine ;
@@ -10,17 +11,38 @@ public class MetricSendSystem : ComponentSystem
1011 {
1112 private Connection connection ;
1213
13- private float timeElapsedSinceUpdate ;
14+ private DateTime timeOfNextUpdate ;
15+ private DateTime timeOfLastUpdate ;
1416
15- private readonly Queue < float > fpsMeasurements = new Queue < float > ( ) ;
16- private const int MaxFpsSamples = 50 ;
17- private const float TimeBetweenMetricUpdatesSecs = 2.0f ;
17+ private const double TimeBetweenMetricUpdatesSecs = 2 ;
1818 private const int DefaultTargetFrameRate = 60 ;
1919
20+ private double targetFps ;
21+
22+ private int lastFrameCount ;
23+ private double calculatedFps ;
24+
25+ // We use exponential smoothing for the FPS metric
26+ // larger value == more smoothing, 0 = no smoothing
27+ // 0 <= smoothing < 1
28+ private const double smoothing = 0 ;
29+
30+ private static readonly Metrics WorkerMetrics = new Metrics ( ) ;
31+
2032 protected override void OnCreateManager ( )
2133 {
2234 base . OnCreateManager ( ) ;
2335 connection = World . GetExistingManager < WorkerSystem > ( ) . Connection ;
36+
37+ targetFps = Application . targetFrameRate == - 1
38+ ? DefaultTargetFrameRate
39+ : Application . targetFrameRate ;
40+
41+ lastFrameCount = Time . frameCount ;
42+ calculatedFps = targetFps ;
43+
44+ timeOfLastUpdate = DateTime . Now ;
45+ timeOfNextUpdate = timeOfLastUpdate . AddSeconds ( TimeBetweenMetricUpdatesSecs ) ;
2446 }
2547
2648 protected override void OnUpdate ( )
@@ -30,54 +52,34 @@ protected override void OnUpdate()
3052 return ;
3153 }
3254
33- timeElapsedSinceUpdate += Time . deltaTime ;
34-
35- AddFpsSample ( ) ;
36- if ( timeElapsedSinceUpdate >= TimeBetweenMetricUpdatesSecs )
55+ if ( DateTime . Now >= timeOfNextUpdate )
3756 {
38- timeElapsedSinceUpdate = 0 ;
39- var fps = CalculateFps ( ) ;
40- var load = DefaultLoadCalculation ( fps ) ;
41- var metrics = new Improbable . Worker . Metrics
42- {
43- Load = load
44- } ;
45- connection . SendMetrics ( metrics ) ;
46- }
47- }
57+ CalculateFps ( ) ;
58+ WorkerMetrics . GaugeMetrics [ "Dynamic.FPS" ] = calculatedFps ;
59+ WorkerMetrics . GaugeMetrics [ "Unity used heap size" ] = GC . GetTotalMemory ( false ) ;
60+ WorkerMetrics . Load = CalculateLoad ( ) ;
4861
49- private static float DefaultLoadCalculation ( float fps )
50- {
51- float targetFps = Application . targetFrameRate ;
62+ connection . SendMetrics ( WorkerMetrics ) ;
5263
53- if ( targetFps == - 1 )
54- {
55- targetFps = DefaultTargetFrameRate ;
64+ timeOfLastUpdate = DateTime . Now ;
65+ timeOfNextUpdate = timeOfLastUpdate . AddSeconds ( TimeBetweenMetricUpdatesSecs ) ;
5666 }
57-
58- return Mathf . Max ( 0.0f , ( targetFps - fps ) / ( 0.5f * targetFps ) ) ;
5967 }
6068
61- private void AddFpsSample ( )
69+ // Load defined as performance relative to target FPS.
70+ // i.e. a load of 0.5 means that the worker is hitting the target FPS
71+ // but achieving less than half the target FPS takes load above 1.0
72+ private double CalculateLoad ( )
6273 {
63- if ( fpsMeasurements . Count == MaxFpsSamples )
64- {
65- fpsMeasurements . Dequeue ( ) ;
66- }
67-
68- fpsMeasurements . Enqueue ( 1.0f / Time . deltaTime ) ;
74+ return Math . Max ( 0.0d , 0.5d * targetFps / calculatedFps ) ;
6975 }
7076
71- private float CalculateFps ( )
77+ private void CalculateFps ( )
7278 {
73- var fps = 0.0f ;
74- foreach ( var measurement in fpsMeasurements )
75- {
76- fps += measurement ;
77- }
78-
79- fps /= fpsMeasurements . Count ;
80- return fps ;
79+ var frameCount = Time . frameCount - lastFrameCount ;
80+ lastFrameCount = Time . frameCount ;
81+ var rawFps = frameCount / ( DateTime . Now - timeOfLastUpdate ) . TotalSeconds ;
82+ calculatedFps = ( rawFps * ( 1 - smoothing ) ) + ( calculatedFps * smoothing ) ;
8183 }
8284 }
8385}
0 commit comments