public static void TryRecycle_PersistentAggregator(IMetricSeriesAggregator accumulatorAggregator)
        {
            var startTS = new DateTimeOffset(2017, 9, 25, 17, 0, 0, TimeSpan.FromHours(-8));
            var endTS   = new DateTimeOffset(2017, 9, 25, 17, 1, 0, TimeSpan.FromHours(-8));

            long periodStringDef   = (long)(endTS - default(DateTimeOffset)).TotalMilliseconds;
            long periodStringStart = (long)(endTS - startTS).TotalMilliseconds;

            {
                accumulatorAggregator.TrackValue(10);

                MetricAggregate aggregate = accumulatorAggregator.CreateAggregateUnsafe(endTS);
                TestUtil.Util.ValidateNumericAggregateValues(aggregate, name: "null", count: 0, sum: 10.0, max: 10.0, min: 10.0, stdDev: 0, timestamp: default(DateTimeOffset), periodMs: periodStringDef, aggKindMoniker: "Microsoft.Azure.Accumulator");

                accumulatorAggregator.Reset(startTS, valueFilter: null);

                accumulatorAggregator.TrackValue(0);
                accumulatorAggregator.TrackValue(10);
                accumulatorAggregator.TrackValue(20);

                aggregate = accumulatorAggregator.CreateAggregateUnsafe(endTS);
                TestUtil.Util.ValidateNumericAggregateValues(aggregate, name: "null", count: 0, sum: 30.0, max: 30.0, min: 0.0, stdDev: 0, timestamp: startTS, periodMs: periodStringStart, aggKindMoniker: "Microsoft.Azure.Accumulator");

                bool canRecycle = accumulatorAggregator.TryRecycle();

                Assert.IsFalse(canRecycle);

                aggregate = accumulatorAggregator.CreateAggregateUnsafe(endTS);
                TestUtil.Util.ValidateNumericAggregateValues(aggregate, name: "null", count: 2, sum: 30.0, max: 30.0, min: 0.0, stdDev: 5.0, timestamp: startTS, periodMs: periodStringStart, aggKindMoniker: "Microsoft.Azure.Accumulator");
            }
        }
Exemple #2
0
        /// <summary>
        /// The lifetime of an aggragator can easily be a minute or so. So, it is a relatively small object that can easily get into Gen-2 GC heap,
        /// but then will need to be reclaimed from there relatively quickly. This can lead to a fragmentation of Gen-2 heap. To avoid this we employ
        /// a simple form of object pooling: Each data series keeps an instance of a past aggregator and tries to reuse it.
        /// Aggregator implementations which believe that they are too expensive to recycle for this, can opt out of this strategy by returning FALSE from
        /// their CanRecycle property.
        /// </summary>
        /// <param name="aggregationCycleKind">The kind of the metric aggregation cycle.</param>
        /// <returns>An empty aggregator.</returns>
        private IMetricSeriesAggregator GetRecycledAggregatorInstance(MetricAggregationCycleKind aggregationCycleKind)
        {
            if (this.requiresPersistentAggregator)
            {
                return(null);
            }

            IMetricSeriesAggregator aggregator = null;

            switch (aggregationCycleKind)
            {
            case CycleKind.Default:
                aggregator = Interlocked.Exchange(ref this.aggregatorRecycleCacheDefault, null);
                break;

            case CycleKind.QuickPulse:
                aggregator = Interlocked.Exchange(ref this.aggregatorRecycleCacheQuickPulse, null);
                break;

            case CycleKind.Custom:
                aggregator = Interlocked.Exchange(ref this.aggregatorRecycleCacheCustom, null);
                break;
            }

            if (aggregator == null)
            {
                return(null);
            }

            if (aggregator.TryRecycle())
            {
                return(aggregator);
            }

            return(null);
        }