< 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:179
Uncovered lines:18
Coverable lines:197
Total lines:417
Line coverage:90.8% (179 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%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
 54335        private SceneMetricsModel maxCountValue = new SceneMetricsModel();
 54336        private SceneMetricsModel currentCountValue = new SceneMetricsModel();
 54337        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            {
 9645                UpdateMetrics();
 9646                return currentCountValue.Clone();
 47            }
 48        }
 49
 56950        public SceneMetricsModel maxCount => maxCountValue.Clone();
 51
 744252        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
 53369        public SceneMetricsCounter(DataStore_WorldObjects dataStore)
 70        {
 53371            this.data = dataStore;
 53372        }
 73
 74        public void Configure(string sceneId, Vector2Int scenePosition, int sceneParcelCount)
 75        {
 53676            this.sceneId = sceneId;
 53677            this.scenePosition = scenePosition;
 53678            this.sceneParcelCount = sceneParcelCount;
 79
 53680            Assert.IsTrue( !string.IsNullOrEmpty(sceneId), "Scene must have an ID!" );
 53681            maxCountValue = ComputeMaxCount();
 53682        }
 83
 84        public void Dispose()
 85        {
 54386        }
 87
 88
 89        public void Enable()
 90        {
 53691            if ( enabled )
 092                return;
 93
 53694            var sceneData = data.sceneData[sceneId];
 95
 53696            sceneData.materials.OnAdded += OnDataChanged;
 53697            sceneData.materials.OnRemoved += OnDataChanged;
 98
 53699            sceneData.textures.OnAdded += OnTextureAdded;
 536100            sceneData.textures.OnRemoved += OnTextureRemoved;
 101
 536102            sceneData.meshes.OnAdded += OnMeshAdded;
 536103            sceneData.meshes.OnRemoved += OnMeshRemoved;
 104
 536105            sceneData.animationClips.OnAdded += OnAnimationClipAdded;
 536106            sceneData.animationClips.OnRemoved += OnAnimationClipRemoved;
 107
 536108            sceneData.animationClipSize.OnChange += OnAnimationClipSizeChange;
 536109            sceneData.meshDataSize.OnChange += OnMeshDataSizeChange;
 110
 536111            sceneData.audioClips.OnAdded += OnAudioClipAdded;
 536112            sceneData.audioClips.OnRemoved += OnAudioClipRemoved;
 113
 536114            sceneData.renderers.OnAdded += OnDataChanged;
 536115            sceneData.renderers.OnRemoved += OnDataChanged;
 116
 536117            sceneData.owners.OnAdded += OnDataChanged;
 536118            sceneData.owners.OnRemoved += OnDataChanged;
 119
 536120            sceneData.triangles.OnChange += OnDataChanged;
 121
 536122            enabled = true;
 536123        }
 124
 125        public void Disable()
 126        {
 537127            if ( !enabled )
 11128                return;
 129
 526130            var sceneData = data.sceneData[sceneId];
 131
 526132            sceneData.materials.OnAdded -= OnDataChanged;
 526133            sceneData.materials.OnRemoved -= OnDataChanged;
 134
 526135            sceneData.textures.OnAdded -= OnTextureAdded;
 526136            sceneData.textures.OnRemoved -= OnTextureRemoved;
 137
 526138            sceneData.meshes.OnAdded -= OnMeshAdded;
 526139            sceneData.meshes.OnRemoved -= OnMeshRemoved;
 140
 526141            sceneData.animationClipSize.OnChange -= OnAnimationClipSizeChange;
 526142            sceneData.meshDataSize.OnChange -= OnMeshDataSizeChange;
 143
 526144            sceneData.audioClips.OnAdded -= OnAudioClipAdded;
 526145            sceneData.audioClips.OnRemoved -= OnAudioClipRemoved;
 146
 526147            sceneData.animationClips.OnAdded -= OnDataChanged;
 526148            sceneData.animationClips.OnRemoved -= OnDataChanged;
 149
 526150            sceneData.renderers.OnAdded -= OnDataChanged;
 526151            sceneData.renderers.OnRemoved -= OnDataChanged;
 152
 526153            sceneData.owners.OnAdded -= OnDataChanged;
 526154            sceneData.owners.OnRemoved -= OnDataChanged;
 155
 526156            sceneData.triangles.OnChange -= OnDataChanged;
 157
 526158            enabled = false;
 526159        }
 160
 161        private SceneMetricsModel ComputeMaxCount()
 162        {
 541163            var result = new SceneMetricsModel();
 164
 541165            float log = Mathf.Log(sceneParcelCount + 1, 2);
 541166            float lineal = sceneParcelCount;
 167
 541168            result.triangles = (int) (lineal * LimitsConfig.triangles);
 541169            result.bodies = (int) (lineal * LimitsConfig.bodies);
 541170            result.entities = (int) (lineal * LimitsConfig.entities);
 541171            result.materials = (int) (log * LimitsConfig.materials);
 541172            result.textures = (int) (log * LimitsConfig.textures);
 541173            result.meshes = (int) (log * LimitsConfig.meshes);
 541174            result.sceneHeight = (int) (log * LimitsConfig.height);
 175
 541176            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        {
 3586208            dirty = true;
 3586209        }
 210
 211        public void SendEvent()
 212        {
 3665213            if (!dirty)
 3474214                return;
 215
 191216            dirty = false;
 217
 191218            UpdateMetrics();
 219
 191220            Interface.WebInterface.ReportOnMetricsUpdate(sceneId, currentCountValue.ToMetricsModel(), maxCount.ToMetrics
 191221        }
 222
 223        void OnMeshAdded(Mesh mesh)
 224        {
 404225            if (mesh == null)
 0226                return;
 227#if UNITY_EDITOR || DEVELOPMENT_BUILD
 404228            currentCountValue.meshMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(mesh);
 229#endif
 404230            MarkDirty();
 404231        }
 232
 233        void OnMeshRemoved(Mesh mesh)
 234        {
 132235            if (mesh == null)
 0236                return;
 237#if UNITY_EDITOR || DEVELOPMENT_BUILD
 132238            currentCountValue.meshMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(mesh);
 239#endif
 132240            MarkDirty();
 132241        }
 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        {
 194304            if (texture == null)
 0305                return;
 306
 194307            MarkDirty();
 308
 194309            if (texture is Texture2D tex2D)
 310            {
 311#if UNITY_EDITOR || DEVELOPMENT_BUILD
 194312                currentCountValue.textureMemoryProfiler += Profiler.GetRuntimeMemorySizeLong(tex2D);
 313#endif
 194314                currentCountValue.textureMemoryScore += MetricsScoreUtils.ComputeTextureScore(tex2D);
 315            }
 194316        }
 317
 318        void OnTextureRemoved(Texture texture)
 319        {
 43320            if (texture == null)
 0321                return;
 322
 43323            MarkDirty();
 324
 43325            if (texture is Texture2D tex2D)
 326            {
 327#if UNITY_EDITOR || DEVELOPMENT_BUILD
 43328                currentCountValue.textureMemoryProfiler -= Profiler.GetRuntimeMemorySizeLong(tex2D);
 329#endif
 43330                currentCountValue.textureMemoryScore -= MetricsScoreUtils.ComputeTextureScore(tex2D);
 331            }
 43332        }
 333
 334        void OnDataChanged<T>(T obj)
 335            where T : class
 336        {
 851337            MarkDirty();
 851338        }
 339
 340        void OnDataChanged(int obj1, int obj2)
 341        {
 488342            MarkDirty();
 488343        }
 344
 345        void OnDataChanged(long obj1)
 346        {
 1332347            MarkDirty();
 1332348        }
 349
 350        private void UpdateMetrics()
 351        {
 292352            if (string.IsNullOrEmpty(sceneId) || data == null || !data.sceneData.ContainsKey(sceneId))
 0353                return;
 354
 292355            if (data != null && data.sceneData.ContainsKey(sceneId))
 356            {
 292357                var sceneData = data.sceneData[sceneId];
 358
 292359                if (sceneData != null)
 360                {
 292361                    currentCountValue.materials = sceneData.materials.Count();
 292362                    currentCountValue.textures = sceneData.textures.Count();
 292363                    currentCountValue.meshes = sceneData.meshes.Count();
 292364                    currentCountValue.entities = sceneData.owners.Count();
 292365                    currentCountValue.bodies = sceneData.renderers.Count();
 292366                    currentCountValue.triangles = sceneData.triangles.Get() / 3;
 367                }
 368            }
 369
 292370            logger.Verbose($"Current metrics: {currentCountValue}");
 292371            RaiseMetricsUpdate();
 292372        }
 373
 374        private void UpdateWorstMetricsOffense()
 375        {
 292376            DataStore_SceneMetrics metricsData = DataStore.i.Get<DataStore_SceneMetrics>();
 377
 292378            if ( maxCountValue != null && metricsData.worstMetricOffenseComputeEnabled.Get() )
 379            {
 292380                bool isOffending = currentCountValue > maxCountValue;
 381
 292382                if ( !isOffending )
 291383                    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        {
 292409            UpdateWorstMetricsOffense();
 292410            if (!currentCountValue.Equals(lastCountValue))
 411            {
 170412                lastCountValue = currentCountValue;
 170413                OnMetricsUpdated?.Invoke(this);
 414            }
 122415        }
 416    }
 417}