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 ;
@@ -16,17 +17,38 @@ public class MetricSendSystem : ComponentSystem
1617 {
1718 private Connection connection ;
1819
19- private float timeElapsedSinceUpdate ;
20+ private DateTime timeOfNextUpdate ;
21+ private DateTime timeOfLastUpdate ;
2022
21- private readonly Queue < float > fpsMeasurements = new Queue < float > ( ) ;
22- private const int MaxFpsSamples = 50 ;
23- private const float TimeBetweenMetricUpdatesSecs = 2.0f ;
23+ private const double TimeBetweenMetricUpdatesSecs = 2 ;
2424 private const int DefaultTargetFrameRate = 60 ;
2525
26+ private double targetFps ;
27+
28+ private int lastFrameCount ;
29+ private double calculatedFps ;
30+
31+ // We use exponential smoothing for the FPS metric
32+ // larger value == more smoothing, 0 = no smoothing
33+ // 0 <= smoothing < 1
34+ private const double smoothing = 0 ;
35+
36+ private static readonly Metrics WorkerMetrics = new Metrics ( ) ;
37+
2638 protected override void OnCreateManager ( )
2739 {
2840 base . OnCreateManager ( ) ;
2941 connection = World . GetExistingManager < WorkerSystem > ( ) . Connection ;
42+
43+ targetFps = Application . targetFrameRate == - 1
44+ ? DefaultTargetFrameRate
45+ : Application . targetFrameRate ;
46+
47+ lastFrameCount = Time . frameCount ;
48+ calculatedFps = targetFps ;
49+
50+ timeOfLastUpdate = DateTime . Now ;
51+ timeOfNextUpdate = timeOfLastUpdate . AddSeconds ( TimeBetweenMetricUpdatesSecs ) ;
3052 }
3153
3254 protected override void OnUpdate ( )
@@ -36,54 +58,34 @@ protected override void OnUpdate()
3658 return ;
3759 }
3860
39- timeElapsedSinceUpdate += Time . deltaTime ;
40-
41- AddFpsSample ( ) ;
42- if ( timeElapsedSinceUpdate >= TimeBetweenMetricUpdatesSecs )
61+ if ( DateTime . Now >= timeOfNextUpdate )
4362 {
44- timeElapsedSinceUpdate = 0 ;
45- var fps = CalculateFps ( ) ;
46- var load = DefaultLoadCalculation ( fps ) ;
47- var metrics = new Improbable . Worker . Metrics
48- {
49- Load = load
50- } ;
51- connection . SendMetrics ( metrics ) ;
52- }
53- }
63+ CalculateFps ( ) ;
64+ WorkerMetrics . GaugeMetrics [ "Dynamic.FPS" ] = calculatedFps ;
65+ WorkerMetrics . GaugeMetrics [ "Unity used heap size" ] = GC . GetTotalMemory ( false ) ;
66+ WorkerMetrics . Load = CalculateLoad ( ) ;
5467
55- private static float DefaultLoadCalculation ( float fps )
56- {
57- float targetFps = Application . targetFrameRate ;
68+ connection . SendMetrics ( WorkerMetrics ) ;
5869
59- if ( targetFps == - 1 )
60- {
61- targetFps = DefaultTargetFrameRate ;
70+ timeOfLastUpdate = DateTime . Now ;
71+ timeOfNextUpdate = timeOfLastUpdate . AddSeconds ( TimeBetweenMetricUpdatesSecs ) ;
6272 }
63-
64- return Mathf . Max ( 0.0f , ( targetFps - fps ) / ( 0.5f * targetFps ) ) ;
6573 }
6674
67- private void AddFpsSample ( )
75+ // Load defined as performance relative to target FPS.
76+ // i.e. a load of 0.5 means that the worker is hitting the target FPS
77+ // but achieving less than half the target FPS takes load above 1.0
78+ private double CalculateLoad ( )
6879 {
69- if ( fpsMeasurements . Count == MaxFpsSamples )
70- {
71- fpsMeasurements . Dequeue ( ) ;
72- }
73-
74- fpsMeasurements . Enqueue ( 1.0f / Time . deltaTime ) ;
80+ return Math . Max ( 0.0d , 0.5d * targetFps / calculatedFps ) ;
7581 }
7682
77- private float CalculateFps ( )
83+ private void CalculateFps ( )
7884 {
79- var fps = 0.0f ;
80- foreach ( var measurement in fpsMeasurements )
81- {
82- fps += measurement ;
83- }
84-
85- fps /= fpsMeasurements . Count ;
86- return fps ;
85+ var frameCount = Time . frameCount - lastFrameCount ;
86+ lastFrameCount = Time . frameCount ;
87+ var rawFps = frameCount / ( DateTime . Now - timeOfLastUpdate ) . TotalSeconds ;
88+ calculatedFps = ( rawFps * ( 1 - smoothing ) ) + ( calculatedFps * smoothing ) ;
8789 }
8890 }
8991}
0 commit comments