< Summary

Class:DCL.SceneMetricsCounter
Assembly:MainScripts
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/WorldRuntime/SceneMetricsCounter/SceneMetricsCounter.cs
Covered lines:142
Uncovered lines:14
Coverable lines:156
Total lines:333
Line coverage:91% (142 of 156)
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%
Disable()0%220100%
ComputeMaxCount()0%110100%
IsInsideTheLimits()0%8.57068.75%
MarkDirty()0%2100%
SendEvent()0%220100%
OnAudioClipAdded(...)0%110100%
OnAudioClipRemoved(...)0%110100%
OnMeshDataSizeChange(...)0%110100%
OnAnimationClipSizeChange(...)0%110100%
OnTextureAdded(...)0%220100%
OnTextureRemoved(...)0%220100%
OnDataChanged[T](...)0%110100%
OnDataChanged(...)0%110100%
UpdateMetrics()0%5.015092.86%
UpdateWorstMetricsOffense()0%7.237083.33%
RaiseMetricsUpdate()0%2.152066.67%

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
 51435        private SceneMetricsModel maxCountValue = new SceneMetricsModel();
 51436        private SceneMetricsModel currentCountValue = new SceneMetricsModel();
 37
 38        public SceneMetricsModel currentCount
 39        {
 40            get
 41            {
 9642                UpdateMetrics();
 9643                return currentCountValue.Clone();
 44            }
 45        }
 46
 73947        public SceneMetricsModel maxCount => maxCountValue.Clone();
 48
 049        public bool dirty { get; private set; }
 50
 51        private string sceneId;
 52
 53        private Vector2Int scenePosition;
 54
 55        private int sceneParcelCount;
 56
 57        private DataStore_WorldObjects data;
 58        private bool enabled = false;
 59
 1060        public SceneMetricsCounter(DataStore_WorldObjects dataStore, string sceneId, Vector2Int scenePosition, int scene
 61        {
 1062            this.data = dataStore;
 1063            Configure(sceneId, scenePosition, sceneParcelCount);
 1064        }
 65
 50466        public SceneMetricsCounter(DataStore_WorldObjects dataStore)
 67        {
 50468            this.data = dataStore;
 50469        }
 70
 71        public void Configure(string sceneId, Vector2Int scenePosition, int sceneParcelCount)
 72        {
 51173            this.sceneId = sceneId;
 51174            this.scenePosition = scenePosition;
 51175            this.sceneParcelCount = sceneParcelCount;
 76
 51177            Assert.IsTrue( !string.IsNullOrEmpty(sceneId), "Scene must have an ID!" );
 51178            maxCountValue = ComputeMaxCount();
 51179        }
 80
 81        public void Dispose()
 82        {
 50483        }
 84
 85
 86        public void Enable()
 87        {
 51188            if ( enabled )
 089                return;
 90
 51191            var sceneData = data.sceneData[sceneId];
 92
 51193            sceneData.materials.OnAdded += OnDataChanged;
 51194            sceneData.materials.OnRemoved += OnDataChanged;
 95
 51196            sceneData.textures.OnAdded += OnTextureAdded;
 51197            sceneData.textures.OnRemoved += OnTextureRemoved;
 98
 51199            sceneData.meshes.OnAdded += OnDataChanged;
 511100            sceneData.meshes.OnRemoved += OnDataChanged;
 101
 511102            sceneData.animationClipSize.OnChange += OnAnimationClipSizeChange;
 511103            sceneData.meshDataSize.OnChange += OnMeshDataSizeChange;
 104
 511105            sceneData.audioClips.OnAdded += OnAudioClipAdded;
 511106            sceneData.audioClips.OnRemoved += OnAudioClipRemoved;
 107
 511108            sceneData.renderers.OnAdded += OnDataChanged;
 511109            sceneData.renderers.OnRemoved += OnDataChanged;
 110
 511111            sceneData.owners.OnAdded += OnDataChanged;
 511112            sceneData.owners.OnRemoved += OnDataChanged;
 113
 511114            sceneData.triangles.OnChange += OnDataChanged;
 115
 511116            enabled = true;
 511117        }
 118
 119        public void Disable()
 120        {
 504121            if ( !enabled )
 3122                return;
 123
 501124            var sceneData = data.sceneData[sceneId];
 125
 501126            sceneData.materials.OnAdded -= OnDataChanged;
 501127            sceneData.materials.OnRemoved -= OnDataChanged;
 128
 501129            sceneData.textures.OnAdded -= OnTextureAdded;
 501130            sceneData.textures.OnRemoved -= OnTextureRemoved;
 131
 501132            sceneData.meshes.OnAdded -= OnDataChanged;
 501133            sceneData.meshes.OnRemoved -= OnDataChanged;
 134
 501135            sceneData.animationClipSize.OnChange -= OnAnimationClipSizeChange;
 501136            sceneData.meshDataSize.OnChange -= OnMeshDataSizeChange;
 137
 501138            sceneData.audioClips.OnAdded -= OnAudioClipAdded;
 501139            sceneData.audioClips.OnRemoved -= OnAudioClipRemoved;
 140
 501141            sceneData.renderers.OnAdded -= OnDataChanged;
 501142            sceneData.renderers.OnRemoved -= OnDataChanged;
 143
 501144            sceneData.owners.OnAdded -= OnDataChanged;
 501145            sceneData.owners.OnRemoved -= OnDataChanged;
 146
 501147            sceneData.triangles.OnChange -= OnDataChanged;
 148
 501149            enabled = false;
 501150        }
 151
 152        private SceneMetricsModel ComputeMaxCount()
 153        {
 516154            var result = new SceneMetricsModel();
 155
 516156            float log = Mathf.Log(sceneParcelCount + 1, 2);
 516157            float lineal = sceneParcelCount;
 158
 516159            result.triangles = (int) (lineal * LimitsConfig.triangles);
 516160            result.bodies = (int) (lineal * LimitsConfig.bodies);
 516161            result.entities = (int) (lineal * LimitsConfig.entities);
 516162            result.materials = (int) (log * LimitsConfig.materials);
 516163            result.textures = (int) (log * LimitsConfig.textures);
 516164            result.meshes = (int) (log * LimitsConfig.meshes);
 516165            result.sceneHeight = (int) (log * LimitsConfig.height);
 166
 516167            return result;
 168        }
 169
 170        public bool IsInsideTheLimits()
 171        {
 5172            UpdateMetrics();
 5173            SceneMetricsModel limits = ComputeMaxCount();
 5174            SceneMetricsModel usage = currentCountValue;
 175
 5176            if (usage.triangles > limits.triangles)
 0177                return false;
 178
 5179            if (usage.bodies > limits.bodies)
 0180                return false;
 181
 5182            if (usage.entities > limits.entities)
 1183                return false;
 184
 4185            if (usage.materials > limits.materials)
 0186                return false;
 187
 4188            if (usage.textures > limits.textures)
 0189                return false;
 190
 4191            if (usage.meshes > limits.meshes)
 0192                return false;
 193
 4194            return true;
 195        }
 196
 197        private void MarkDirty()
 198        {
 0199            dirty = true;
 0200        }
 201
 202        public void SendEvent()
 203        {
 678204            if (!dirty)
 482205                return;
 206
 196207            dirty = false;
 208
 196209            UpdateMetrics();
 210
 196211            Interface.WebInterface.ReportOnMetricsUpdate(sceneId, currentCountValue.ToMetricsModel(), maxCount.ToMetrics
 196212        }
 213
 214        void OnAudioClipAdded(AudioClip audioClip)
 215        {
 17216            MarkDirty();
 17217            currentCountValue.audioClipMemory += MetricsScoreUtils.ComputeAudioClipScore(audioClip);
 17218        }
 219
 220        void OnAudioClipRemoved(AudioClip audioClip)
 221        {
 3222            MarkDirty();
 3223            currentCountValue.audioClipMemory -= MetricsScoreUtils.ComputeAudioClipScore(audioClip);
 3224        }
 225
 226
 227        private void OnMeshDataSizeChange(long current, long previous)
 228        {
 85229            MarkDirty();
 85230            currentCountValue.meshMemory = current;
 85231        }
 232
 233        void OnAnimationClipSizeChange(long animationClipSize, long previous)
 234        {
 13235            MarkDirty();
 13236            currentCountValue.animationClipMemory = animationClipSize;
 13237        }
 238
 239        void OnTextureAdded(Texture texture)
 240        {
 175241            MarkDirty();
 242
 175243            if (texture is Texture2D tex2D)
 244            {
 175245                currentCountValue.textureMemory += MetricsScoreUtils.ComputeTextureScore(tex2D);
 246            }
 175247        }
 248
 249        void OnTextureRemoved(Texture texture)
 250        {
 45251            MarkDirty();
 252
 45253            if (texture is Texture2D tex2D)
 254            {
 45255                currentCountValue.textureMemory -= MetricsScoreUtils.ComputeTextureScore(tex2D);
 256            }
 45257        }
 258
 259        void OnDataChanged<T>(T obj)
 260            where T : class
 261        {
 2486262            MarkDirty();
 2486263        }
 264
 265        void OnDataChanged(int obj1, int obj2)
 266        {
 449267            MarkDirty();
 449268        }
 269
 270        private void UpdateMetrics()
 271        {
 297272            if (string.IsNullOrEmpty(sceneId))
 0273                return;
 274
 297275            if (data != null && data.sceneData.ContainsKey(sceneId))
 276            {
 297277                var sceneData = data.sceneData[sceneId];
 278
 297279                if (sceneData != null)
 280                {
 297281                    currentCountValue.materials = sceneData.materials.Count();
 297282                    currentCountValue.textures = sceneData.textures.Count();
 297283                    currentCountValue.meshes = sceneData.meshes.Count();
 297284                    currentCountValue.entities = sceneData.owners.Count();
 297285                    currentCountValue.bodies = sceneData.renderers.Count();
 297286                    currentCountValue.triangles = sceneData.triangles.Get() / 3;
 287                }
 288            }
 289
 297290            logger.Verbose($"Current metrics: {currentCountValue}");
 297291            RaiseMetricsUpdate();
 297292        }
 293
 294        private void UpdateWorstMetricsOffense()
 295        {
 297296            DataStore_SceneMetrics metricsData = DataStore.i.Get<DataStore_SceneMetrics>();
 297
 297298            if ( maxCountValue != null && metricsData.worstMetricOffenseComputeEnabled.Get() )
 299            {
 297300                bool isOffending = currentCountValue > maxCountValue;
 301
 297302                if ( !isOffending )
 296303                    return;
 304
 1305                bool firstOffense = false;
 306
 1307                if (!metricsData.worstMetricOffenses.ContainsKey(sceneId))
 308                {
 1309                    firstOffense = true;
 1310                    metricsData.worstMetricOffenses[sceneId] = currentCountValue.Clone();
 311                }
 312
 1313                SceneMetricsModel worstOffense = metricsData.worstMetricOffenses[sceneId];
 1314                SceneMetricsModel currentOffense = maxCountValue - currentCountValue;
 315
 1316                if ( firstOffense )
 1317                    logger.Verbose($"New offending scene {sceneId} ({scenePosition})!\n{currentCountValue}");
 318
 1319                if ( currentOffense < worstOffense )
 1320                    return;
 321
 0322                metricsData.worstMetricOffenses[sceneId] = currentOffense;
 0323                logger.Verbose($"New offending scene {sceneId} {scenePosition}!\nmetrics: {currentCountValue}\nlimits: {
 324            }
 0325        }
 326
 327        private void RaiseMetricsUpdate()
 328        {
 297329            UpdateWorstMetricsOffense();
 297330            OnMetricsUpdated?.Invoke(this);
 0331        }
 332    }
 333}