< 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
 39835        private SceneMetricsModel maxCountValue = new SceneMetricsModel();
 39836        private SceneMetricsModel currentCountValue = new SceneMetricsModel();
 39837        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
 33750        public SceneMetricsModel maxCount => maxCountValue.Clone();
 51
 668752        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
 38869        public SceneMetricsCounter(DataStore_WorldObjects dataStore)
 70        {
 38871            this.data = dataStore;
 38872        }
 73
 74        public void Configure(int sceneNumber, Vector2Int scenePosition, int sceneParcelCount)
 75        {
 39176            this.sceneNumber = sceneNumber;
 39177            this.scenePosition = scenePosition;
 39178            this.sceneParcelCount = sceneParcelCount;
 79
 39180            Assert.IsTrue( sceneNumber > 0, "Scene must have a scene number!" );
 39181            maxCountValue = ComputeMaxCount();
 39182        }
 83
 84        public void Dispose()
 85        {
 39886        }
 87
 88        public void Enable()
 89        {
 39190            if ( enabled )
 091                return;
 92
 39193            var sceneData = data.sceneData[sceneNumber];
 94
 39195            sceneData.materials.OnAdded += OnDataChanged;
 39196            sceneData.materials.OnRemoved += OnDataChanged;
 97
 39198            sceneData.textures.OnAdded += OnTextureAdded;
 39199            sceneData.textures.OnRemoved += OnTextureRemoved;
 100
 391101            sceneData.meshes.OnAdded += OnMeshAdded;
 391102            sceneData.meshes.OnRemoved += OnMeshRemoved;
 103
 391104            sceneData.animationClips.OnAdded += OnAnimationClipAdded;
 391105            sceneData.animationClips.OnRemoved += OnAnimationClipRemoved;
 106
 391107            sceneData.animationClipSize.OnChange += OnAnimationClipSizeChange;
 391108            sceneData.meshDataSize.OnChange += OnMeshDataSizeChange;
 109
 391110            sceneData.audioClips.OnAdded += OnAudioClipAdded;
 391111            sceneData.audioClips.OnRemoved += OnAudioClipRemoved;
 112
 391113            sceneData.renderers.OnAdded += OnDataChanged;
 391114            sceneData.renderers.OnRemoved += OnDataChanged;
 115
 391116            sceneData.owners.OnAdded += OnDataChanged;
 391117            sceneData.owners.OnRemoved += OnDataChanged;
 118
 391119            sceneData.triangles.OnChange += OnDataChanged;
 120
 391121            enabled = true;
 391122        }
 123
 124        public void Disable()
 125        {
 388126            if ( !enabled )
 7127                return;
 128
 381129            var sceneData = data.sceneData[sceneNumber];
 130
 381131            sceneData.materials.OnAdded -= OnDataChanged;
 381132            sceneData.materials.OnRemoved -= OnDataChanged;
 133
 381134            sceneData.textures.OnAdded -= OnTextureAdded;
 381135            sceneData.textures.OnRemoved -= OnTextureRemoved;
 136
 381137            sceneData.meshes.OnAdded -= OnMeshAdded;
 381138            sceneData.meshes.OnRemoved -= OnMeshRemoved;
 139
 381140            sceneData.animationClipSize.OnChange -= OnAnimationClipSizeChange;
 381141            sceneData.meshDataSize.OnChange -= OnMeshDataSizeChange;
 142
 381143            sceneData.audioClips.OnAdded -= OnAudioClipAdded;
 381144            sceneData.audioClips.OnRemoved -= OnAudioClipRemoved;
 145
 381146            sceneData.animationClips.OnAdded -= OnDataChanged;
 381147            sceneData.animationClips.OnRemoved -= OnDataChanged;
 148
 381149            sceneData.renderers.OnAdded -= OnDataChanged;
 381150            sceneData.renderers.OnRemoved -= OnDataChanged;
 151
 381152            sceneData.owners.OnAdded -= OnDataChanged;
 381153            sceneData.owners.OnRemoved -= OnDataChanged;
 154
 381155            sceneData.triangles.OnChange -= OnDataChanged;
 156
 381157            enabled = false;
 381158        }
 159
 160        private SceneMetricsModel ComputeMaxCount()
 161        {
 391162            var result = new SceneMetricsModel();
 163
 391164            float log = Mathf.Log(sceneParcelCount + 1, 2);
 391165            float lineal = sceneParcelCount;
 166
 391167            result.triangles = (int) (lineal * LimitsConfig.triangles);
 391168            result.bodies = (int) (lineal * LimitsConfig.bodies);
 391169            result.entities = (int) (lineal * LimitsConfig.entities);
 391170            result.materials = (int) (log * LimitsConfig.materials);
 391171            result.textures = (int) (log * LimitsConfig.textures);
 391172            result.meshes = (int) (log * LimitsConfig.meshes);
 391173            result.sceneHeight = (int) (log * LimitsConfig.height);
 174
 391175            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        {
 3227207            dirty = true;
 3227208        }
 209
 210        public void SendEvent()
 211        {
 3286212            if (!dirty)
 3112213                return;
 214
 174215            dirty = false;
 216
 174217            UpdateMetrics();
 218
 174219            Interface.WebInterface.ReportOnMetricsUpdate(sceneNumber, currentCountValue.ToMetricsModel(), maxCount.ToMet
 174220        }
 221
 222        void OnMeshAdded(Mesh mesh)
 223        {
 392224            if (mesh == null)
 0225                return;
 226#if UNITY_EDITOR || DEVELOPMENT_BUILD
 392227            currentCountValue.meshMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(mesh);
 228#endif
 392229            MarkDirty();
 392230        }
 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        {
 830336            MarkDirty();
 830337        }
 338
 339        void OnDataChanged(int obj1, int obj2)
 340        {
 479341            MarkDirty();
 479342        }
 343
 344        void OnDataChanged(long obj1)
 345        {
 1035346            MarkDirty();
 1035347        }
 348
 349        private void UpdateMetrics()
 350        {
 253351            if (sceneNumber <= 0 || data == null || !data.sceneData.ContainsKey(sceneNumber))
 0352                return;
 353
 253354            if (data != null && data.sceneData.ContainsKey(sceneNumber))
 355            {
 253356                var sceneData = data.sceneData[sceneNumber];
 357
 253358                if (sceneData != null)
 359                {
 253360                    currentCountValue.materials = sceneData.materials.Count();
 253361                    currentCountValue.textures = sceneData.textures.Count();
 253362                    currentCountValue.meshes = sceneData.meshes.Count();
 253363                    currentCountValue.entities = sceneData.owners.Count();
 253364                    currentCountValue.bodies = sceneData.renderers.Count();
 253365                    currentCountValue.triangles = sceneData.triangles.Get() / 3;
 366                }
 367            }
 368
 253369            logger.Verbose($"Current metrics: {currentCountValue}");
 253370            RaiseMetricsUpdate();
 253371        }
 372
 373        private void UpdateWorstMetricsOffense()
 374        {
 253375            DataStore_SceneMetrics metricsData = DataStore.i.Get<DataStore_SceneMetrics>();
 376
 253377            if ( maxCountValue != null && metricsData.worstMetricOffenseComputeEnabled.Get() )
 378            {
 253379                bool isOffending = currentCountValue > maxCountValue;
 380
 253381                if ( !isOffending )
 252382                    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        {
 253408            UpdateWorstMetricsOffense();
 253409            if (!currentCountValue.Equals(lastCountValue))
 410            {
 151411                lastCountValue = currentCountValue;
 151412                OnMetricsUpdated?.Invoke(this);
 413            }
 102414        }
 415    }
 416}