< 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:176
Uncovered lines:21
Coverable lines:197
Total lines:417
Line coverage:89.3% (176 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%8.57068.75%
MarkDirty()0%2100%
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
 54635        private SceneMetricsModel maxCountValue = new SceneMetricsModel();
 54636        private SceneMetricsModel currentCountValue = new SceneMetricsModel();
 54637        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            {
 10045                UpdateMetrics();
 10046                return currentCountValue.Clone();
 47            }
 48        }
 49
 57550        public SceneMetricsModel maxCount => maxCountValue.Clone();
 51
 052        public bool dirty { get; private set; }
 53
 54        private string sceneId;
 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, string sceneId, Vector2Int scenePosition, int scene
 64        {
 1065            this.data = dataStore;
 1066            Configure(sceneId, scenePosition, sceneParcelCount);
 1067        }
 68
 53669        public SceneMetricsCounter(DataStore_WorldObjects dataStore)
 70        {
 53671            this.data = dataStore;
 53672        }
 73
 74        public void Configure(string sceneId, Vector2Int scenePosition, int sceneParcelCount)
 75        {
 53976            this.sceneId = sceneId;
 53977            this.scenePosition = scenePosition;
 53978            this.sceneParcelCount = sceneParcelCount;
 79
 53980            Assert.IsTrue( !string.IsNullOrEmpty(sceneId), "Scene must have an ID!" );
 53981            maxCountValue = ComputeMaxCount();
 53982        }
 83
 84        public void Dispose()
 85        {
 53686        }
 87
 88
 89        public void Enable()
 90        {
 53991            if ( enabled )
 092                return;
 93
 53994            var sceneData = data.sceneData[sceneId];
 95
 53996            sceneData.materials.OnAdded += OnDataChanged;
 53997            sceneData.materials.OnRemoved += OnDataChanged;
 98
 53999            sceneData.textures.OnAdded += OnTextureAdded;
 539100            sceneData.textures.OnRemoved += OnTextureRemoved;
 101
 539102            sceneData.meshes.OnAdded += OnMeshAdded;
 539103            sceneData.meshes.OnRemoved += OnMeshRemoved;
 104
 539105            sceneData.animationClips.OnAdded += OnAnimationClipAdded;
 539106            sceneData.animationClips.OnRemoved += OnAnimationClipRemoved;
 107
 539108            sceneData.animationClipSize.OnChange += OnAnimationClipSizeChange;
 539109            sceneData.meshDataSize.OnChange += OnMeshDataSizeChange;
 110
 539111            sceneData.audioClips.OnAdded += OnAudioClipAdded;
 539112            sceneData.audioClips.OnRemoved += OnAudioClipRemoved;
 113
 539114            sceneData.renderers.OnAdded += OnDataChanged;
 539115            sceneData.renderers.OnRemoved += OnDataChanged;
 116
 539117            sceneData.owners.OnAdded += OnDataChanged;
 539118            sceneData.owners.OnRemoved += OnDataChanged;
 119
 539120            sceneData.triangles.OnChange += OnDataChanged;
 121
 539122            enabled = true;
 539123        }
 124
 125        public void Disable()
 126        {
 540127            if ( !enabled )
 11128                return;
 129
 529130            var sceneData = data.sceneData[sceneId];
 131
 529132            sceneData.materials.OnAdded -= OnDataChanged;
 529133            sceneData.materials.OnRemoved -= OnDataChanged;
 134
 529135            sceneData.textures.OnAdded -= OnTextureAdded;
 529136            sceneData.textures.OnRemoved -= OnTextureRemoved;
 137
 529138            sceneData.meshes.OnAdded -= OnMeshAdded;
 529139            sceneData.meshes.OnRemoved -= OnMeshRemoved;
 140
 529141            sceneData.animationClipSize.OnChange -= OnAnimationClipSizeChange;
 529142            sceneData.meshDataSize.OnChange -= OnMeshDataSizeChange;
 143
 529144            sceneData.audioClips.OnAdded -= OnAudioClipAdded;
 529145            sceneData.audioClips.OnRemoved -= OnAudioClipRemoved;
 146
 529147            sceneData.animationClips.OnAdded -= OnDataChanged;
 529148            sceneData.animationClips.OnRemoved -= OnDataChanged;
 149
 529150            sceneData.renderers.OnAdded -= OnDataChanged;
 529151            sceneData.renderers.OnRemoved -= OnDataChanged;
 152
 529153            sceneData.owners.OnAdded -= OnDataChanged;
 529154            sceneData.owners.OnRemoved -= OnDataChanged;
 155
 529156            sceneData.triangles.OnChange -= OnDataChanged;
 157
 529158            enabled = false;
 529159        }
 160
 161        private SceneMetricsModel ComputeMaxCount()
 162        {
 544163            var result = new SceneMetricsModel();
 164
 544165            float log = Mathf.Log(sceneParcelCount + 1, 2);
 544166            float lineal = sceneParcelCount;
 167
 544168            result.triangles = (int) (lineal * LimitsConfig.triangles);
 544169            result.bodies = (int) (lineal * LimitsConfig.bodies);
 544170            result.entities = (int) (lineal * LimitsConfig.entities);
 544171            result.materials = (int) (log * LimitsConfig.materials);
 544172            result.textures = (int) (log * LimitsConfig.textures);
 544173            result.meshes = (int) (log * LimitsConfig.meshes);
 544174            result.sceneHeight = (int) (log * LimitsConfig.height);
 175
 544176            return result;
 177        }
 178
 179        public bool IsInsideTheLimits()
 180        {
 5181            UpdateMetrics();
 5182            SceneMetricsModel limits = ComputeMaxCount();
 5183            SceneMetricsModel usage = currentCountValue;
 184
 5185            if (usage.triangles > limits.triangles)
 0186                return false;
 187
 5188            if (usage.bodies > limits.bodies)
 0189                return false;
 190
 5191            if (usage.entities > limits.entities)
 1192                return false;
 193
 4194            if (usage.materials > limits.materials)
 0195                return false;
 196
 4197            if (usage.textures > limits.textures)
 0198                return false;
 199
 4200            if (usage.meshes > limits.meshes)
 0201                return false;
 202
 4203            return true;
 204        }
 205
 206        private void MarkDirty()
 207        {
 0208            dirty = true;
 0209        }
 210
 211        public void SendEvent()
 212        {
 782213            if (!dirty)
 598214                return;
 215
 184216            dirty = false;
 217
 184218            UpdateMetrics();
 219
 184220            Interface.WebInterface.ReportOnMetricsUpdate(sceneId, currentCountValue.ToMetricsModel(), maxCount.ToMetrics
 184221        }
 222
 223        void OnMeshAdded(Mesh mesh)
 224        {
 407225            if (mesh == null)
 0226                return;
 227#if UNITY_EDITOR || DEVELOPMENT_BUILD
 407228            currentCountValue.meshMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(mesh);
 229#endif
 407230            MarkDirty();
 407231        }
 232
 233        void OnMeshRemoved(Mesh mesh)
 234        {
 134235            if (mesh == null)
 0236                return;
 237#if UNITY_EDITOR || DEVELOPMENT_BUILD
 134238            currentCountValue.meshMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(mesh);
 239#endif
 134240            MarkDirty();
 134241        }
 242
 243        void OnAnimationClipAdded(AnimationClip animationClip)
 244        {
 12245            if (animationClip == null)
 0246                return;
 247
 248#if UNITY_EDITOR || DEVELOPMENT_BUILD
 12249            currentCountValue.animationClipMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(animationClip);
 250#endif
 12251            MarkDirty();
 12252        }
 253
 254        void OnAnimationClipRemoved(AnimationClip animationClip)
 255        {
 2256            if (animationClip == null)
 0257                return;
 258
 259#if UNITY_EDITOR || DEVELOPMENT_BUILD
 2260            currentCountValue.animationClipMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(animationClip);
 261#endif
 2262            MarkDirty();
 2263        }
 264
 265        void OnAudioClipAdded(AudioClip audioClip)
 266        {
 18267            if (audioClip == null)
 0268                return;
 269
 18270            MarkDirty();
 271#if UNITY_EDITOR || DEVELOPMENT_BUILD
 18272            currentCountValue.audioClipMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(audioClip);
 273#endif
 18274            currentCountValue.audioClipMemoryScore += MetricsScoreUtils.ComputeAudioClipScore(audioClip);
 18275        }
 276
 277        void OnAudioClipRemoved(AudioClip audioClip)
 278        {
 3279            if (audioClip == null)
 0280                return;
 281
 3282            MarkDirty();
 283#if UNITY_EDITOR || DEVELOPMENT_BUILD
 3284            currentCountValue.audioClipMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(audioClip);
 285#endif
 3286            currentCountValue.audioClipMemoryScore -= MetricsScoreUtils.ComputeAudioClipScore(audioClip);
 3287        }
 288
 289
 290        private void OnMeshDataSizeChange(long current, long previous)
 291        {
 92292            MarkDirty();
 92293            currentCountValue.meshMemoryScore = current;
 92294        }
 295
 296        void OnAnimationClipSizeChange(long animationClipSize, long previous)
 297        {
 15298            MarkDirty();
 15299            currentCountValue.animationClipMemoryScore = animationClipSize;
 15300        }
 301
 302        void OnTextureAdded(Texture texture)
 303        {
 199304            if (texture == null)
 0305                return;
 306
 199307            MarkDirty();
 308
 199309            if (texture is Texture2D tex2D)
 310            {
 311#if UNITY_EDITOR || DEVELOPMENT_BUILD
 199312                currentCountValue.textureMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(tex2D);
 313#endif
 199314                currentCountValue.textureMemoryScore += MetricsScoreUtils.ComputeTextureScore(tex2D);
 315            }
 199316        }
 317
 318        void OnTextureRemoved(Texture texture)
 319        {
 48320            if (texture == null)
 0321                return;
 322
 48323            MarkDirty();
 324
 48325            if (texture is Texture2D tex2D)
 326            {
 327#if UNITY_EDITOR || DEVELOPMENT_BUILD
 48328                currentCountValue.textureMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(tex2D);
 329#endif
 48330                currentCountValue.textureMemoryScore -= MetricsScoreUtils.ComputeTextureScore(tex2D);
 331            }
 48332        }
 333
 334        void OnDataChanged<T>(T obj)
 335            where T : class
 336        {
 860337            MarkDirty();
 860338        }
 339
 340        void OnDataChanged(int obj1, int obj2)
 341        {
 493342            MarkDirty();
 493343        }
 344
 345        void OnDataChanged(long obj1)
 346        {
 1349347            MarkDirty();
 1349348        }
 349
 350        private void UpdateMetrics()
 351        {
 289352            if (string.IsNullOrEmpty(sceneId) || data == null || !data.sceneData.ContainsKey(sceneId))
 0353                return;
 354
 289355            if (data != null && data.sceneData.ContainsKey(sceneId))
 356            {
 289357                var sceneData = data.sceneData[sceneId];
 358
 289359                if (sceneData != null)
 360                {
 289361                    currentCountValue.materials = sceneData.materials.Count();
 289362                    currentCountValue.textures = sceneData.textures.Count();
 289363                    currentCountValue.meshes = sceneData.meshes.Count();
 289364                    currentCountValue.entities = sceneData.owners.Count();
 289365                    currentCountValue.bodies = sceneData.renderers.Count();
 289366                    currentCountValue.triangles = sceneData.triangles.Get() / 3;
 367                }
 368            }
 369
 289370            logger.Verbose($"Current metrics: {currentCountValue}");
 289371            RaiseMetricsUpdate();
 289372        }
 373
 374        private void UpdateWorstMetricsOffense()
 375        {
 289376            DataStore_SceneMetrics metricsData = DataStore.i.Get<DataStore_SceneMetrics>();
 377
 289378            if ( maxCountValue != null && metricsData.worstMetricOffenseComputeEnabled.Get() )
 379            {
 289380                bool isOffending = currentCountValue > maxCountValue;
 381
 289382                if ( !isOffending )
 288383                    return;
 384
 1385                bool firstOffense = false;
 386
 1387                if (!metricsData.worstMetricOffenses.ContainsKey(sceneId))
 388                {
 1389                    firstOffense = true;
 1390                    metricsData.worstMetricOffenses[sceneId] = currentCountValue.Clone();
 391                }
 392
 1393                SceneMetricsModel worstOffense = metricsData.worstMetricOffenses[sceneId];
 1394                SceneMetricsModel currentOffense = maxCountValue - currentCountValue;
 395
 1396                if ( firstOffense )
 1397                    logger.Verbose($"New offending scene {sceneId} ({scenePosition})!\n{currentCountValue}");
 398
 1399                if ( currentOffense < worstOffense )
 1400                    return;
 401
 0402                metricsData.worstMetricOffenses[sceneId] = currentOffense;
 0403                logger.Verbose($"New offending scene {sceneId} {scenePosition}!\nmetrics: {currentCountValue}\nlimits: {
 404            }
 0405        }
 406
 407        private void RaiseMetricsUpdate()
 408        {
 289409            UpdateWorstMetricsOffense();
 289410            if (!currentCountValue.Equals(lastCountValue))
 411            {
 171412                lastCountValue = currentCountValue;
 171413                OnMetricsUpdated?.Invoke(this);
 414            }
 118415        }
 416    }
 417}