< 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: 112
Uncovered lines: 0
Coverable lines: 112
Total lines: 239
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>
 1628        private readonly List<IPerformanceReporter> _reporters = new List<IPerformanceReporter>();
 29
 30        /// <summary>
 31        /// Container for storing performance data
 32        /// </summary>
 1633        private readonly PerformanceData _performanceData = new PerformanceData
 1634        {
 1635            Data = new List<PerformanceDataItem>()
 1636        };
 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        {
 2449            get => _measurePerformance;
 50            set
 1051            {
 1052                _measurePerformance = value;
 3253                _reporters.ForEach(reporter => reporter.MeasurePerformance = value);
 1054            }
 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>
 1265        public PerformanceAggregator()
 1266        {
 1267        }
 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>
 473        public PerformanceAggregator(List<IPerformanceReporter> reporters)
 474        {
 2875            foreach (var performanceReporter in reporters)
 876            {
 877                RegisterReporter(performanceReporter);
 878            }
 479        }
 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)
 2688        {
 2689            if (reporter == null)
 290                return;
 2491            _reporters.Add(reporter);
 2492            reporter.PerformanceDataUpdated += AddData;
 2493            SyncFrameId();
 2494            reporter.MeasurePerformance = MeasurePerformance;
 2695        }
 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)
 6103        {
 6104            if (reporter == null)
 2105                return;
 4106            _reporters.Remove(reporter);
 4107            reporter.PerformanceDataUpdated -= AddData;
 6108        }
 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)
 54120        {
 54121            var item = CreateNewDataItem();
 54122            lock (_performanceData)
 54123            {
 54124                var existingProcessData = _performanceData.Data.FirstOrDefault(elem =>
 374125                                        (elem.Stage == PerformanceDataStage.ProcessingData || elem.Stage == PerformanceD
 126
 54127                var existingFilterData = _performanceData.Data.FirstOrDefault(elem =>
 374128                    elem.Stage == PerformanceDataStage.FilterDataStored && elem.FrameId == data.FrameId);
 129
 54130                if (data.Stage == PerformanceDataStage.Start)
 46131                {
 46132                    item.Stage = PerformanceDataStage.FilterDataStored;
 133
 46134                    if (existingFilterData != null)
 40135                    {
 136                        // increment frame id: incomplete sample - subsequent filter samples
 40137                        _frameId++;
 40138                        existingFilterData.Stage = PerformanceDataStage.Complete;
 40139                        item.FrameId = _frameId;
 40140                    }
 6141                    else if (existingProcessData != null)
 2142                    {
 2143                      item = existingProcessData;
 2144                      item.Stage = PerformanceDataStage.Complete;
 2145                      _performanceData.Data.Remove(existingProcessData);
 146
 147                      // increment frame id: data complete (filter + process data)
 2148                      _frameId++;
 2149                    }
 150
 46151                    item.Filter = data.Filter;
 46152                    _performanceData.Data.Add(item);
 153
 46154                }
 8155                else if (data.Stage == PerformanceDataStage.ProcessingData)
 8156                {
 8157                    if (existingProcessData != null)
 2158                    {
 159                        // increment frame id: incomplete sample - subsequent process samples
 2160                        _frameId++;
 2161                        existingProcessData.Stage = PerformanceDataStage.Complete;
 2162                        item.FrameId = _frameId;
 163
 2164                    }
 6165                    else if (existingFilterData != null)
 2166                    {
 2167                        item = existingFilterData;
 2168                        item.Stage = PerformanceDataStage.Complete;
 2169                        _performanceData.Data.Remove(existingFilterData);
 170
 171                        // increment frame id: data complete (filter + process data)
 2172                        _frameId++;
 2173                    }
 174
 8175                    item.Process = data.Process;
 8176                    item.FrameStart = data.FrameStart;
 8177                    item.FrameEnd = data.FrameEnd;
 8178                    _performanceData.Data.Add(item);
 8179                }
 180
 54181                SyncFrameId();
 182
 54183                CleanupRecords();
 184
 54185            }
 186
 404187            var completed = _performanceData.Data.Where(elem => elem.Stage == PerformanceDataStage.Complete).ToList();
 54188            PerformanceDataUpdated?.Invoke(this, new PerformanceData
 54189            {
 54190                Data = completed
 54191            });
 54192        }
 193
 194        /// <summary>
 195        /// Set local frame Id for all registered reporters
 196        /// </summary>
 197        private void SyncFrameId()
 78198        {
 172199            _reporters.ForEach(reporter => reporter.UpdateFrameId(_frameId));
 78200        }
 201
 202        /// <summary>
 203        /// Create a new <see cref="PerformanceDataItem"/>  with the current frame Id, setting the <see cref="Performanc
 204        /// </summary>
 205        /// <returns>the created <see cref="PerformanceDataItem"/></returns>
 206        private PerformanceDataItem CreateNewDataItem()
 54207        {
 54208            var result = new PerformanceDataItem
 54209            {
 54210                FrameId = _frameId,
 54211                FrameStart = DateTime.Now.Ticks,
 54212                Stage = PerformanceDataStage.Incomplete
 54213            };
 214
 54215            return result;
 54216        }
 217
 218        /// <summary>
 219        /// Remove all records except the first <see cref="MaxNumIncompleteRecords"/> elements.
 220        /// Set all items with the stage <see cref="PerformanceDataStage.Incomplete"/> to <see cref="PerformanceDataStag
 221        /// </summary>
 222        private void CleanupRecords()
 54223        {
 54224            if (_performanceData.Data.Count > MaxPerformanceRecords)
 20225                _performanceData.Data.RemoveRange(0, _performanceData.Data.Count - MaxPerformanceRecords);
 54226        }
 227
 228        /// <summary>
 229        /// Dispose method to unregister reporters during disposal.
 230        /// </summary>
 231        public void Dispose()
 2232        {
 14233            foreach (var performanceReporter in _reporters.ToList())
 4234            {
 4235                UnregisterReporter(performanceReporter);
 4236            }
 2237        }
 238    }
 239}