< 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

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
 39235        private SceneMetricsModel maxCountValue = new SceneMetricsModel();
 39236        private SceneMetricsModel currentCountValue = new SceneMetricsModel();
 39237        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
 33550        public SceneMetricsModel maxCount => maxCountValue.Clone();
 51
 669452        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
 38269        public SceneMetricsCounter(DataStore_WorldObjects dataStore)
 70        {
 38271            this.data = dataStore;
 38272        }
 73
 74        public void Configure(int sceneNumber, Vector2Int scenePosition, int sceneParcelCount)
 75        {
 38776            this.sceneNumber = sceneNumber;
 38777            this.scenePosition = scenePosition;
 38778            this.sceneParcelCount = sceneParcelCount;
 79
 38780            Assert.IsTrue( sceneNumber > 0, "Scene must have a scene number!" );
 38781            maxCountValue = ComputeMaxCount();
 38782        }
 83
 84        public void Dispose()
 85        {
 39286        }
 87
 88        public void Enable()
 89        {
 38790            if ( enabled )
 091                return;
 92
 38793            var sceneData = data.sceneData[sceneNumber];
 94
 38795            sceneData.materials.OnAdded += OnDataChanged;
 38796            sceneData.materials.OnRemoved += OnDataChanged;
 97
 38798            sceneData.textures.OnAdded += OnTextureAdded;
 38799            sceneData.textures.OnRemoved += OnTextureRemoved;
 100
 387101            sceneData.meshes.OnAdded += OnMeshAdded;
 387102            sceneData.meshes.OnRemoved += OnMeshRemoved;
 103
 387104            sceneData.animationClips.OnAdded += OnAnimationClipAdded;
 387105            sceneData.animationClips.OnRemoved += OnAnimationClipRemoved;
 106
 387107            sceneData.animationClipSize.OnChange += OnAnimationClipSizeChange;
 387108            sceneData.meshDataSize.OnChange += OnMeshDataSizeChange;
 109
 387110            sceneData.audioClips.OnAdded += OnAudioClipAdded;
 387111            sceneData.audioClips.OnRemoved += OnAudioClipRemoved;
 112
 387113            sceneData.renderers.OnAdded += OnDataChanged;
 387114            sceneData.renderers.OnRemoved += OnDataChanged;
 115
 387116            sceneData.owners.OnAdded += OnDataChanged;
 387117            sceneData.owners.OnRemoved += OnDataChanged;
 118
 387119            sceneData.triangles.OnChange += OnDataChanged;
 120
 387121            enabled = true;
 387122        }
 123
 124        public void Disable()
 125        {
 382126            if ( !enabled )
 5127                return;
 128
 377129            var sceneData = data.sceneData[sceneNumber];
 130
 377131            sceneData.materials.OnAdded -= OnDataChanged;
 377132            sceneData.materials.OnRemoved -= OnDataChanged;
 133
 377134            sceneData.textures.OnAdded -= OnTextureAdded;
 377135            sceneData.textures.OnRemoved -= OnTextureRemoved;
 136
 377137            sceneData.meshes.OnAdded -= OnMeshAdded;
 377138            sceneData.meshes.OnRemoved -= OnMeshRemoved;
 139
 377140            sceneData.animationClipSize.OnChange -= OnAnimationClipSizeChange;
 377141            sceneData.meshDataSize.OnChange -= OnMeshDataSizeChange;
 142
 377143            sceneData.audioClips.OnAdded -= OnAudioClipAdded;
 377144            sceneData.audioClips.OnRemoved -= OnAudioClipRemoved;
 145
 377146            sceneData.animationClips.OnAdded -= OnDataChanged;
 377147            sceneData.animationClips.OnRemoved -= OnDataChanged;
 148
 377149            sceneData.renderers.OnAdded -= OnDataChanged;
 377150            sceneData.renderers.OnRemoved -= OnDataChanged;
 151
 377152            sceneData.owners.OnAdded -= OnDataChanged;
 377153            sceneData.owners.OnRemoved -= OnDataChanged;
 154
 377155            sceneData.triangles.OnChange -= OnDataChanged;
 156
 377157            enabled = false;
 377158        }
 159
 160        private SceneMetricsModel ComputeMaxCount()
 161        {
 387162            var result = new SceneMetricsModel();
 163
 387164            float log = Mathf.Log(sceneParcelCount + 1, 2);
 387165            float lineal = sceneParcelCount;
 166
 387167            result.triangles = (int) (lineal * LimitsConfig.triangles);
 387168            result.bodies = (int) (lineal * LimitsConfig.bodies);
 387169            result.entities = (int) (lineal * LimitsConfig.entities);
 387170            result.materials = (int) (log * LimitsConfig.materials);
 387171            result.textures = (int) (log * LimitsConfig.textures);
 387172            result.meshes = (int) (log * LimitsConfig.meshes);
 387173            result.sceneHeight = (int) (log * LimitsConfig.height);
 174
 387175            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        {
 3228207            dirty = true;
 3228208        }
 209
 210        public void SendEvent()
 211        {
 3291212            if (!dirty)
 3116213                return;
 214
 175215            dirty = false;
 216
 175217            UpdateMetrics();
 218
 175219            Interface.WebInterface.ReportOnMetricsUpdate(sceneNumber, currentCountValue.ToMetricsModel(), maxCount.ToMet
 175220        }
 221
 222        void OnMeshAdded(Mesh mesh)
 223        {
 393224            if (mesh == null)
 0225                return;
 226#if UNITY_EDITOR || DEVELOPMENT_BUILD
 393227            currentCountValue.meshMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(mesh);
 228#endif
 393229            MarkDirty();
 393230        }
 231
 232        void OnMeshRemoved(Mesh mesh)
 233        {
 133234            if (mesh == null)
 0235                return;
 236#if UNITY_EDITOR || DEVELOPMENT_BUILD
 133237            currentCountValue.meshMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(mesh);
 238#endif
 133239            MarkDirty();
 133240        }
 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        {
 78291            MarkDirty();
 78292            currentCountValue.meshMemoryScore = current;
 78293        }
 294
 295        void OnAnimationClipSizeChange(long animationClipSize, long previous)
 296        {
 15297            MarkDirty();
 15298            currentCountValue.animationClipMemoryScore = animationClipSize;
 15299        }
 300
 301        void OnTextureAdded(Texture texture)
 302        {
 183303            if (texture == null)
 0304                return;
 305
 183306            MarkDirty();
 307
 183308            if (texture is Texture2D tex2D)
 309            {
 310#if UNITY_EDITOR || DEVELOPMENT_BUILD
 183311                currentCountValue.textureMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(tex2D);
 312#endif
 183313                currentCountValue.textureMemoryScore += MetricsScoreUtils.ComputeTextureScore(tex2D);
 314            }
 183315        }
 316
 317        void OnTextureRemoved(Texture texture)
 318        {
 47319            if (texture == null)
 0320                return;
 321
 47322            MarkDirty();
 323
 47324            if (texture is Texture2D tex2D)
 325            {
 326#if UNITY_EDITOR || DEVELOPMENT_BUILD
 47327                currentCountValue.textureMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(tex2D);
 328#endif
 47329                currentCountValue.textureMemoryScore -= MetricsScoreUtils.ComputeTextureScore(tex2D);
 330            }
 47331        }
 332
 333        void OnDataChanged<T>(T obj)
 334            where T : class
 335        {
 831336            MarkDirty();
 831337        }
 338
 339        void OnDataChanged(int obj1, int obj2)
 340        {
 480341            MarkDirty();
 480342        }
 343
 344        void OnDataChanged(long obj1)
 345        {
 1033346            MarkDirty();
 1033347        }
 348
 349        private void UpdateMetrics()
 350        {
 254351            if (sceneNumber <= 0 || data == null || !data.sceneData.ContainsKey(sceneNumber))
 0352                return;
 353
 254354            if (data != null && data.sceneData.ContainsKey(sceneNumber))
 355            {
 254356                var sceneData = data.sceneData[sceneNumber];
 357
 254358                if (sceneData != null)
 359                {
 254360                    currentCountValue.materials = sceneData.materials.Count();
 254361                    currentCountValue.textures = sceneData.textures.Count();
 254362                    currentCountValue.meshes = sceneData.meshes.Count();
 254363                    currentCountValue.entities = sceneData.owners.Count();
 254364                    currentCountValue.bodies = sceneData.renderers.Count();
 254365                    currentCountValue.triangles = sceneData.triangles.Get() / 3;
 366                }
 367            }
 368
 254369            logger.Verbose($"Current metrics: {currentCountValue}");
 254370            RaiseMetricsUpdate();
 254371        }
 372
 373        private void UpdateWorstMetricsOffense()
 374        {
 254375            DataStore_SceneMetrics metricsData = DataStore.i.Get<DataStore_SceneMetrics>();
 376
 254377            if ( maxCountValue != null && metricsData.worstMetricOffenseComputeEnabled.Get() )
 378            {
 254379                bool isOffending = currentCountValue > maxCountValue;
 380
 254381                if ( !isOffending )
 253382                    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        {
 254408            UpdateWorstMetricsOffense();
 254409            if (!currentCountValue.Equals(lastCountValue))
 410            {
 155411                lastCountValue = currentCountValue;
 155412                OnMetricsUpdated?.Invoke(this);
 413            }
 99414        }
 415    }
 416}