< Summary

Class:DCL.SceneMetricsCounter
Assembly:DCL.Runtime
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneMetricsCounter/SceneMetricsCounter.cs
Covered lines:168
Uncovered lines:29
Coverable lines:197
Total lines:416
Line coverage:85.2% (168 of 197)
Covered branches:0
Total branches:0
Covered methods:30
Total methods:31
Method coverage:96.7% (30 of 31)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
SceneMetricsCounter()0%110100%
SceneMetricsCounter(...)0%110100%
SceneMetricsCounter(...)0%110100%
Configure(...)0%110100%
Dispose()0%110100%
Enable()0%22095.45%
Disable()0%220100%
ComputeMaxCount()0%110100%
IsInsideTheLimits()0%56700%
MarkDirty()0%110100%
SendEvent()0%220100%
OnMeshAdded(...)0%2.032080%
OnMeshRemoved(...)0%2.032080%
OnAnimationClipAdded(...)0%2.032080%
OnAnimationClipRemoved(...)0%2.032080%
OnAudioClipAdded(...)0%2.022083.33%
OnAudioClipRemoved(...)0%2.022083.33%
OnMeshDataSizeChange(...)0%110100%
OnAnimationClipSizeChange(...)0%110100%
OnTextureAdded(...)0%3.033085.71%
OnTextureRemoved(...)0%3.033085.71%
OnDataChanged[T](...)0%110100%
OnDataChanged(...)0%110100%
OnDataChanged(...)0%110100%
UpdateMetrics()0%7.027092.86%
UpdateWorstMetricsOffense()0%7.237083.33%
RaiseMetricsUpdate()0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneMetricsCounter/SceneMetricsCounter.cs

#LineLine coverage
 1using System;
 2using DCL.Controllers;
 3using DCL.Interface;
 4using DCL.Models;
 5using System.Collections.Generic;
 6using System.Linq;
 7using UnityEngine;
 8using UnityEngine.Assertions;
 9using UnityEngine.Profiling;
 10
 11namespace DCL
 12{
 13    public sealed class SceneMetricsCounter : ISceneMetricsCounter
 14    {
 15        public static class LimitsConfig
 16        {
 17            // number of entities
 18            public const int entities = 200;
 19
 20            // Number of faces (per parcel)
 21            public const int triangles = 10000;
 22            public const int bodies = 300;
 23            public const int textures = 10;
 24            public const int materials = 20;
 25            public const int meshes = 200;
 26
 27            public const float height = 20;
 28            public const float visibleRadius = 10;
 29        }
 30
 131        private static bool VERBOSE = false;
 132        private static Logger logger = new Logger("SceneMetricsCounter") { verboseEnabled = VERBOSE };
 33        public event Action<ISceneMetricsCounter> OnMetricsUpdated;
 34
 44335        private SceneMetricsModel maxCountValue = new SceneMetricsModel();
 44336        private SceneMetricsModel currentCountValue = new SceneMetricsModel();
 44337        private SceneMetricsModel lastCountValue = new SceneMetricsModel();
 38
 39        // TODO: We should handle this better, right now if we get the current amount of limits, we update the metrics
 40        // So if someone check the current amount when subscribed to the OnMetricsUpdated, we will try to Update the met
 41        public SceneMetricsModel currentCount
 42        {
 43            get
 44            {
 7945                UpdateMetrics();
 7946                return currentCountValue.Clone();
 47            }
 48        }
 49
 36150        public SceneMetricsModel maxCount => maxCountValue.Clone();
 51
 457852        public bool dirty { get; private set; }
 53
 54        private int sceneNumber;
 55
 56        private Vector2Int scenePosition;
 57
 58        private int sceneParcelCount;
 59
 60        private DataStore_WorldObjects data;
 61        private bool enabled = false;
 62
 1063        public SceneMetricsCounter(DataStore_WorldObjects dataStore, int sceneNumber, Vector2Int scenePosition, int scen
 64        {
 1065            this.data = dataStore;
 1066            Configure(sceneNumber, scenePosition, sceneParcelCount);
 1067        }
 68
 43369        public SceneMetricsCounter(DataStore_WorldObjects dataStore)
 70        {
 43371            this.data = dataStore;
 43372        }
 73
 74        public void Configure(int sceneNumber, Vector2Int scenePosition, int sceneParcelCount)
 75        {
 43676            this.sceneNumber = sceneNumber;
 43677            this.scenePosition = scenePosition;
 43678            this.sceneParcelCount = sceneParcelCount;
 79
 43680            Assert.IsTrue( sceneNumber > 0, "Scene must have a scene number!" );
 43681            maxCountValue = ComputeMaxCount();
 43682        }
 83
 84        public void Dispose()
 85        {
 44386        }
 87
 88        public void Enable()
 89        {
 43690            if ( enabled )
 091                return;
 92
 43693            var sceneData = data.sceneData[sceneNumber];
 94
 43695            sceneData.materials.OnAdded += OnDataChanged;
 43696            sceneData.materials.OnRemoved += OnDataChanged;
 97
 43698            sceneData.textures.OnAdded += OnTextureAdded;
 43699            sceneData.textures.OnRemoved += OnTextureRemoved;
 100
 436101            sceneData.meshes.OnAdded += OnMeshAdded;
 436102            sceneData.meshes.OnRemoved += OnMeshRemoved;
 103
 436104            sceneData.animationClips.OnAdded += OnAnimationClipAdded;
 436105            sceneData.animationClips.OnRemoved += OnAnimationClipRemoved;
 106
 436107            sceneData.animationClipSize.OnChange += OnAnimationClipSizeChange;
 436108            sceneData.meshDataSize.OnChange += OnMeshDataSizeChange;
 109
 436110            sceneData.audioClips.OnAdded += OnAudioClipAdded;
 436111            sceneData.audioClips.OnRemoved += OnAudioClipRemoved;
 112
 436113            sceneData.renderers.OnAdded += OnDataChanged;
 436114            sceneData.renderers.OnRemoved += OnDataChanged;
 115
 436116            sceneData.owners.OnAdded += OnDataChanged;
 436117            sceneData.owners.OnRemoved += OnDataChanged;
 118
 436119            sceneData.triangles.OnChange += OnDataChanged;
 120
 436121            enabled = true;
 436122        }
 123
 124        public void Disable()
 125        {
 433126            if ( !enabled )
 7127                return;
 128
 426129            var sceneData = data.sceneData[sceneNumber];
 130
 426131            sceneData.materials.OnAdded -= OnDataChanged;
 426132            sceneData.materials.OnRemoved -= OnDataChanged;
 133
 426134            sceneData.textures.OnAdded -= OnTextureAdded;
 426135            sceneData.textures.OnRemoved -= OnTextureRemoved;
 136
 426137            sceneData.meshes.OnAdded -= OnMeshAdded;
 426138            sceneData.meshes.OnRemoved -= OnMeshRemoved;
 139
 426140            sceneData.animationClipSize.OnChange -= OnAnimationClipSizeChange;
 426141            sceneData.meshDataSize.OnChange -= OnMeshDataSizeChange;
 142
 426143            sceneData.audioClips.OnAdded -= OnAudioClipAdded;
 426144            sceneData.audioClips.OnRemoved -= OnAudioClipRemoved;
 145
 426146            sceneData.animationClips.OnAdded -= OnDataChanged;
 426147            sceneData.animationClips.OnRemoved -= OnDataChanged;
 148
 426149            sceneData.renderers.OnAdded -= OnDataChanged;
 426150            sceneData.renderers.OnRemoved -= OnDataChanged;
 151
 426152            sceneData.owners.OnAdded -= OnDataChanged;
 426153            sceneData.owners.OnRemoved -= OnDataChanged;
 154
 426155            sceneData.triangles.OnChange -= OnDataChanged;
 156
 426157            enabled = false;
 426158        }
 159
 160        private SceneMetricsModel ComputeMaxCount()
 161        {
 436162            var result = new SceneMetricsModel();
 163
 436164            float log = Mathf.Log(sceneParcelCount + 1, 2);
 436165            float lineal = sceneParcelCount;
 166
 436167            result.triangles = (int) (lineal * LimitsConfig.triangles);
 436168            result.bodies = (int) (lineal * LimitsConfig.bodies);
 436169            result.entities = (int) (lineal * LimitsConfig.entities);
 436170            result.materials = (int) (log * LimitsConfig.materials);
 436171            result.textures = (int) (log * LimitsConfig.textures);
 436172            result.meshes = (int) (log * LimitsConfig.meshes);
 436173            result.sceneHeight = (int) (log * LimitsConfig.height);
 174
 436175            return result;
 176        }
 177
 178        public bool IsInsideTheLimits()
 179        {
 0180            UpdateMetrics();
 0181            SceneMetricsModel limits = ComputeMaxCount();
 0182            SceneMetricsModel usage = currentCountValue;
 183
 0184            if (usage.triangles > limits.triangles)
 0185                return false;
 186
 0187            if (usage.bodies > limits.bodies)
 0188                return false;
 189
 0190            if (usage.entities > limits.entities)
 0191                return false;
 192
 0193            if (usage.materials > limits.materials)
 0194                return false;
 195
 0196            if (usage.textures > limits.textures)
 0197                return false;
 198
 0199            if (usage.meshes > limits.meshes)
 0200                return false;
 201
 0202            return true;
 203        }
 204
 205        private void MarkDirty()
 206        {
 3084207            dirty = true;
 3084208        }
 209
 210        public void SendEvent()
 211        {
 1317212            if (!dirty)
 1140213                return;
 214
 177215            dirty = false;
 216
 177217            UpdateMetrics();
 218
 177219            Interface.WebInterface.ReportOnMetricsUpdate(sceneNumber, currentCountValue.ToMetricsModel(), maxCount.ToMet
 177220        }
 221
 222        void OnMeshAdded(Mesh mesh)
 223        {
 347224            if (mesh == null)
 0225                return;
 226#if UNITY_EDITOR || DEVELOPMENT_BUILD
 347227            currentCountValue.meshMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(mesh);
 228#endif
 347229            MarkDirty();
 347230        }
 231
 232        void OnMeshRemoved(Mesh mesh)
 233        {
 127234            if (mesh == null)
 0235                return;
 236#if UNITY_EDITOR || DEVELOPMENT_BUILD
 127237            currentCountValue.meshMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(mesh);
 238#endif
 127239            MarkDirty();
 127240        }
 241
 242        void OnAnimationClipAdded(AnimationClip animationClip)
 243        {
 12244            if (animationClip == null)
 0245                return;
 246
 247#if UNITY_EDITOR || DEVELOPMENT_BUILD
 12248            currentCountValue.animationClipMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(animationClip);
 249#endif
 12250            MarkDirty();
 12251        }
 252
 253        void OnAnimationClipRemoved(AnimationClip animationClip)
 254        {
 2255            if (animationClip == null)
 0256                return;
 257
 258#if UNITY_EDITOR || DEVELOPMENT_BUILD
 2259            currentCountValue.animationClipMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(animationClip);
 260#endif
 2261            MarkDirty();
 2262        }
 263
 264        void OnAudioClipAdded(AudioClip audioClip)
 265        {
 18266            if (audioClip == null)
 0267                return;
 268
 18269            MarkDirty();
 270#if UNITY_EDITOR || DEVELOPMENT_BUILD
 18271            currentCountValue.audioClipMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(audioClip);
 272#endif
 18273            currentCountValue.audioClipMemoryScore += MetricsScoreUtils.ComputeAudioClipScore(audioClip);
 18274        }
 275
 276        void OnAudioClipRemoved(AudioClip audioClip)
 277        {
 3278            if (audioClip == null)
 0279                return;
 280
 3281            MarkDirty();
 282#if UNITY_EDITOR || DEVELOPMENT_BUILD
 3283            currentCountValue.audioClipMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(audioClip);
 284#endif
 3285            currentCountValue.audioClipMemoryScore -= MetricsScoreUtils.ComputeAudioClipScore(audioClip);
 3286        }
 287
 288
 289        private void OnMeshDataSizeChange(long current, long previous)
 290        {
 4291            MarkDirty();
 4292            currentCountValue.meshMemoryScore = current;
 4293        }
 294
 295        void OnAnimationClipSizeChange(long animationClipSize, long previous)
 296        {
 4297            MarkDirty();
 4298            currentCountValue.animationClipMemoryScore = animationClipSize;
 4299        }
 300
 301        void OnTextureAdded(Texture texture)
 302        {
 193303            if (texture == null)
 0304                return;
 305
 193306            MarkDirty();
 307
 193308            if (texture is Texture2D tex2D)
 309            {
 310#if UNITY_EDITOR || DEVELOPMENT_BUILD
 193311                currentCountValue.textureMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(tex2D);
 312#endif
 193313                currentCountValue.textureMemoryScore += MetricsScoreUtils.ComputeTextureScore(tex2D);
 314            }
 193315        }
 316
 317        void OnTextureRemoved(Texture texture)
 318        {
 60319            if (texture == null)
 0320                return;
 321
 60322            MarkDirty();
 323
 60324            if (texture is Texture2D tex2D)
 325            {
 326#if UNITY_EDITOR || DEVELOPMENT_BUILD
 60327                currentCountValue.textureMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(tex2D);
 328#endif
 60329                currentCountValue.textureMemoryScore -= MetricsScoreUtils.ComputeTextureScore(tex2D);
 330            }
 60331        }
 332
 333        void OnDataChanged<T>(T obj)
 334            where T : class
 335        {
 794336            MarkDirty();
 794337        }
 338
 339        void OnDataChanged(int obj1, int obj2)
 340        {
 472341            MarkDirty();
 472342        }
 343
 344        void OnDataChanged(long obj1)
 345        {
 1048346            MarkDirty();
 1048347        }
 348
 349        private void UpdateMetrics()
 350        {
 256351            if (sceneNumber <= 0 || data == null || !data.sceneData.ContainsKey(sceneNumber))
 0352                return;
 353
 256354            if (data != null && data.sceneData.ContainsKey(sceneNumber))
 355            {
 256356                var sceneData = data.sceneData[sceneNumber];
 357
 256358                if (sceneData != null)
 359                {
 256360                    currentCountValue.materials = sceneData.materials.Count();
 256361                    currentCountValue.textures = sceneData.textures.Count();
 256362                    currentCountValue.meshes = sceneData.meshes.Count();
 256363                    currentCountValue.entities = sceneData.owners.Count();
 256364                    currentCountValue.bodies = sceneData.renderers.Count();
 256365                    currentCountValue.triangles = sceneData.triangles.Get() / 3;
 366                }
 367            }
 368
 256369            logger.Verbose($"Current metrics: {currentCountValue}");
 256370            RaiseMetricsUpdate();
 256371        }
 372
 373        private void UpdateWorstMetricsOffense()
 374        {
 256375            DataStore_SceneMetrics metricsData = DataStore.i.Get<DataStore_SceneMetrics>();
 376
 256377            if ( maxCountValue != null && metricsData.worstMetricOffenseComputeEnabled.Get() )
 378            {
 256379                bool isOffending = currentCountValue > maxCountValue;
 380
 256381                if ( !isOffending )
 255382                    return;
 383
 1384                bool firstOffense = false;
 385
 1386                if (!metricsData.worstMetricOffenses.ContainsKey(sceneNumber))
 387                {
 1388                    firstOffense = true;
 1389                    metricsData.worstMetricOffenses[sceneNumber] = currentCountValue.Clone();
 390                }
 391
 1392                SceneMetricsModel worstOffense = metricsData.worstMetricOffenses[sceneNumber];
 1393                SceneMetricsModel currentOffense = maxCountValue - currentCountValue;
 394
 1395                if ( firstOffense )
 1396                    logger.Verbose($"New offending scene with scene number {sceneNumber} ({scenePosition})!\n{currentCou
 397
 1398                if ( currentOffense < worstOffense )
 1399                    return;
 400
 0401                metricsData.worstMetricOffenses[sceneNumber] = currentOffense;
 0402                logger.Verbose($"New offending scene with scene number {sceneNumber} {scenePosition}!\nmetrics: {current
 403            }
 0404        }
 405
 406        private void RaiseMetricsUpdate()
 407        {
 256408            UpdateWorstMetricsOffense();
 256409            if (!currentCountValue.Equals(lastCountValue))
 410            {
 150411                lastCountValue = currentCountValue;
 150412                OnMetricsUpdated?.Invoke(this);
 413            }
 106414        }
 415    }
 416}