< Summary - ReFlex - Library

Information
Class: ReFlex.Core.Common.Components.PerformanceAggregator
Assembly: ReFlex.Core.Common
File(s): D:\a\reflex\reflex\library\src\Core\Common\Components\PerformanceAggregator.cs
Line coverage
100%
Covered lines: 110
Uncovered lines: 0
Coverable lines: 110
Total lines: 236
Line coverage: 100%
Branch coverage
96%
Covered branches: 29
Total branches: 30
Branch coverage: 96.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%
get_MeasurePerformance()100%11100%
set_MeasurePerformance(...)100%11100%
.ctor(...)100%22100%
RegisterReporter(...)100%22100%
UnregisterReporter(...)100%22100%
AddData(...)95%2020100%
SyncFrameId()100%11100%
CreateNewDataItem()100%11100%
CleanupRecords()100%22100%
Dispose()100%22100%

File(s)

D:\a\reflex\reflex\library\src\Core\Common\Components\PerformanceAggregator.cs

#LineLine coverage
 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using ReFlex.Core.Common.Interfaces;
 5using ReFlex.Core.Common.Util;
 6
 7namespace ReFlex.Core.Common.Components
 8{
 9
 10    public class PerformanceAggregator : IPerformanceAggregator, IDisposable
 11    {
 12        /// <summary>
 13        /// Maximum number of performance records to keep
 14        /// </summary>
 15        private const int MaxPerformanceRecords = 10;
 16
 17        [Obsolete]
 18        private const int MaxNumIncompleteRecords = 3;
 19
 20        /// <summary>
 21        /// id of the current frame
 22        /// </summary>
 23        private int _frameId;
 24
 25        /// <summary>
 26        /// List of performance reporters registered with the aggregator
 27        /// </summary>
 828        private readonly List<IPerformanceReporter> _reporters = new List<IPerformanceReporter>();
 29
 30        /// <summary>
 31        /// Container for storing performance data
 32        /// </summary>
 833        private readonly PerformanceData _performanceData = new PerformanceData
 834        {
 835            Data = new List<PerformanceDataItem>()
 836        };
 37
 38        /// <summary>
 39        ///  Flag to determine whether to measure performance or not
 40        /// </summary>
 41        private bool _measurePerformance;
 42
 43        /// <summary>
 44        /// Flag to determine whether to measure performance or not
 45        /// Value is propagated to registered reporters, so they start/stop measuring if this value changes
 46        /// </summary>
 47        public bool MeasurePerformance
 48        {
 1249            get => _measurePerformance;
 50            set
 551            {
 552                _measurePerformance = value;
 1653                _reporters.ForEach(reporter => reporter.MeasurePerformance = value);
 554            }
 55        }
 56
 57        /// <summary>
 58        /// Event triggered when performance data is updated for propagating current performance data
 59        /// </summary>
 60        public event EventHandler<PerformanceData> PerformanceDataUpdated;
 61
 62        /// <summary>
 63        /// Default constructor
 64        /// </summary>
 665        public PerformanceAggregator()
 666        {
 667        }
 68
 69        /// <summary>
 70        /// Constructor with a list of reporters to register during construction
 71        /// </summary>
 72        /// <param name="reporters">Reporters that are to be registered when constructor is executed</param>
 273        public PerformanceAggregator(List<IPerformanceReporter> reporters)
 274        {
 1475            foreach (var performanceReporter in reporters)
 476            {
 477                RegisterReporter(performanceReporter);
 478            }
 279        }
 80
 81        /// <summary>
 82        /// Register a performance reporter with the aggregator.
 83        /// When registering, the Aggregator subscribes to the <see cref="PerformanceDataUpdated"/> event of the reporte
 84        /// The frame id is initially synchronized between reporter and aggregator and the <see cref="MeasurePerformance
 85        /// </summary>
 86        /// <param name="reporter">The Performance Reporter that wil be registered</param>
 87        public void RegisterReporter(IPerformanceReporter reporter)
 1388        {
 1389            if (reporter == null)
 190                return;
 1291            _reporters.Add(reporter);
 1292            reporter.PerformanceDataUpdated += AddData;
 1293            SyncFrameId();
 1294            reporter.MeasurePerformance = MeasurePerformance;
 1395        }
 96
 97        /// <summary>
 98        /// Unregister a performance reporter from the aggregator.
 99        /// Removes reporter from the internal list and unsubscribes from the <see cref="PerformanceDataUpdated"/> event
 100        /// </summary>
 101        /// <param name="reporter">The reporter which is to be removed from the current list of reporters.</param>
 102        public void UnregisterReporter(IPerformanceReporter reporter)
 3103        {
 3104            if (reporter == null)
 1105                return;
 2106            _reporters.Remove(reporter);
 2107            reporter.PerformanceDataUpdated -= AddData;
 3108        }
 109
 110        /// <summary>
 111        /// Event handler to add performance data sent by a reporter.
 112        /// When data is flagged with <see cref="PerformanceDataStage.Start"/>, the filter data is added and the stage i
 113        /// When associated stage is <see cref="PerformanceDataStage.ProcessingData"/>, processing data is merged with e
 114        /// Old records are removed with respect to the specification of <see cref="MaxPerformanceRecords"/>
 115        /// Records with the stage of <see cref="PerformanceDataStage.Complete"/> are propagated using the <see cref="Pe
 116        /// </summary>
 117        /// <param name="sender">The instance issuing the event</param>
 118        /// <param name="data">the updated Performance data record</param>
 119        private void AddData(object sender, PerformanceDataItem data)
 27120        {
 27121            var item = CreateNewDataItem();
 27122            lock (_performanceData)
 27123            {
 27124                var existingProcessData = _performanceData.Data.FirstOrDefault(elem =>
 187125                                        (elem.Stage == PerformanceDataStage.ProcessingData || elem.Stage == PerformanceD
 126
 27127                var existingFilterData = _performanceData.Data.FirstOrDefault(elem =>
 187128                    elem.Stage == PerformanceDataStage.FilterDataStored && elem.FrameId == data.FrameId);
 129
 27130                if (data.Stage == PerformanceDataStage.Start)
 23131                {
 23132                    item.Stage = PerformanceDataStage.FilterDataStored;
 133
 23134                    if (existingFilterData != null)
 20135                    {
 136                        // increment frame id: incomplete sample - subsequent filter samples
 20137                        _frameId++;
 20138                        existingFilterData.Stage = PerformanceDataStage.Complete;
 20139                        item.FrameId = _frameId;
 20140                    }
 3141                    else if (existingProcessData != null)
 1142                    {
 1143                      item = existingProcessData;
 1144                      item.Stage = PerformanceDataStage.Complete;
 1145                      _performanceData.Data.Remove(existingProcessData);
 146
 147                      // increment frame id: data complete (filter + process data)
 1148                      _frameId++;
 1149                    }
 150
 23151                    item.Filter = data.Filter;
 23152                    _performanceData.Data.Add(item);
 153
 23154                }
 4155                else if (data.Stage == PerformanceDataStage.ProcessingData)
 4156                {
 4157                    if (existingProcessData != null)
 1158                    {
 159                        // increment frame id: incomplete sample - subsequent process samples
 1160                        _frameId++;
 1161                        existingProcessData.Stage = PerformanceDataStage.Complete;
 1162                        item.FrameId = _frameId;
 1163                    }
 3164                    else if (existingFilterData != null)
 1165                    {
 1166                        item = existingFilterData;
 1167                        item.Stage = PerformanceDataStage.Complete;
 1168                        _performanceData.Data.Remove(existingFilterData);
 169
 170                        // increment frame id: data complete (filter + process data)
 1171                        _frameId++;
 1172                    }
 173
 4174                    item.Process = data.Process;
 4175                    _performanceData.Data.Add(item);
 4176                }
 177
 27178                SyncFrameId();
 179
 27180                CleanupRecords();
 181
 27182            }
 183
 202184            var completed = _performanceData.Data.Where(elem => elem.Stage == PerformanceDataStage.Complete).ToList();
 27185            PerformanceDataUpdated?.Invoke(this, new PerformanceData
 27186            {
 27187                Data = completed
 27188            });
 27189        }
 190
 191        /// <summary>
 192        /// Set local frame Id for all registered reporters
 193        /// </summary>
 194        private void SyncFrameId()
 39195        {
 86196            _reporters.ForEach(reporter => reporter.UpdateFrameId(_frameId));
 39197        }
 198
 199        /// <summary>
 200        /// Create a new <see cref="PerformanceDataItem"/>  with the current frame Id, setting the <see cref="Performanc
 201        /// </summary>
 202        /// <returns>the created <see cref="PerformanceDataItem"/></returns>
 203        private PerformanceDataItem CreateNewDataItem()
 27204        {
 27205            var result = new PerformanceDataItem
 27206            {
 27207                FrameId = _frameId,
 27208                FrameStart = DateTime.Now.Ticks,
 27209                Stage = PerformanceDataStage.Incomplete
 27210            };
 211
 27212            return result;
 27213        }
 214
 215        /// <summary>
 216        /// Remove all records except the first <see cref="MaxNumIncompleteRecords"/> elements.
 217        /// Set all items with the stage <see cref="PerformanceDataStage.Incomplete"/> to <see cref="PerformanceDataStag
 218        /// </summary>
 219        private void CleanupRecords()
 27220        {
 27221            if (_performanceData.Data.Count > MaxPerformanceRecords)
 10222                _performanceData.Data.RemoveRange(0, _performanceData.Data.Count - MaxPerformanceRecords);
 27223        }
 224
 225        /// <summary>
 226        /// Dispose method to unregister reporters during disposal.
 227        /// </summary>
 228        public void Dispose()
 1229        {
 7230            foreach (var performanceReporter in _reporters.ToList())
 2231            {
 2232                UnregisterReporter(performanceReporter);
 2233            }
 1234        }
 235    }
 236}