public static void TestCriticalProofContainsWithRoundingBruteForce()
        {
            var unitScale = MetricUnitScale.FromEnumValues(typeof(Distance));

            var lastRange = MetricValueHelpers.CreateMetricRange(0, 0);
            int repeats   = 0;
            int increment = 3;

            for (long i = 0; i < int.MaxValue; i += increment)
            {
                // exponential growth as the scale is exponential
                if (++repeats >= 1000 && increment < int.MaxValue / 10)
                {
                    repeats    = 0;
                    increment *= 2;
                }

                lastRange = AssertAssertRoundtripInvariant(i, lastRange, unitScale);
            }

            lastRange = MetricValueHelpers.CreateMetricRange(int.MaxValue, int.MaxValue);
            repeats   = 0;
            increment = int.MaxValue / 200;
            for (long i = int.MaxValue; i > 0; i -= increment)             // reverse order
            {
                // logarithmic decrease as the scale is enumerated in reverse order
                if (++repeats >= 1000 && increment > 10)
                {
                    repeats    = 0;
                    increment /= 2;
                }

                lastRange = AssertAssertRoundtripInvariant(i, lastRange, unitScale);
            }
        }
예제 #2
0
        public static void TestMetricUnitScaleOnes()
        {
            var scale  = MetricUnitScale.FromEnumValues(typeof(MetricEnumOk));
            var scale2 = MetricUnitScale.FromEnumValues(typeof(MetricEnumOk));

            AreSame(scale, scale2);

            var unit = scale[0];

            AreSame(unit, scale[MetricEnumOk.Ones]);
            AreSame(unit, scale["onES"]);             // case-insensitive
            AreSame(unit, scale[1]);
            AreSame(unit, scale[2]);
            AreSame(unit, scale[-2]);
            AreSame(unit, scale[double.NaN]);
            AreSame(unit, scale[MetricRange.Empty]);
            AreSame(unit, scale[new MetricRange(-1, 20000)]);
            AreSame(unit, scale[new MetricRange(-20000, 1)]);
            IsFalse(unit.IsEmpty);
            AreEqual(unit.EnumValue, MetricEnumOk.Ones);
            AreEqual(unit.AppliesFrom, 1);
            AreEqual(unit.ScaleCoefficient, 1);
            AreEqual(unit.RoundingDigits, null);
            AreEqual(unit.DisplayName, "Ones");
        }
        public static void TestCreateMetricRange(double min, double max, string unit, double expectedMin, double expectedMax)
        {
            var unitScale  = MetricUnitScale.FromEnumValues(typeof(Distance));
            var metricUnit = unitScale[unit];
            var range      = MetricValueHelpers.CreateMetricRange(min, max, metricUnit);

            AreEqual(range.Min, expectedMin);
            AreEqual(range.Max, expectedMax);
        }
예제 #4
0
        public static void TestEmptyMetricUnitScale()
        {
            var scale = MetricUnitScale.Empty;

            AreSame(scale, MetricUnitScale.FromEnumValues(null));

            var unit = scale[0];

            IsTrue(unit.IsEmpty);
            AreSame(unit, MetricUnit.Empty);
            AreEqual(unit.EnumValue, null);
            AreEqual(unit.AppliesFrom, 0);
            AreEqual(unit.ScaleCoefficient, 1);
            AreEqual(unit.RoundingDigits, null);
        }
예제 #5
0
        public static void TestMetricUnitScaleArgValidation()
        {
            DoesNotThrow(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumOk)));
            DoesNotThrow(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumZero)));

            // DONTTOUCH: called twice to proof that error is cached.
            Throws <ArgumentException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumEmpty)));
            Throws <ArgumentException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumEmpty)));

            Throws <ArgumentException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumNextLessThanPrevious)));
            Throws <ArgumentException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumNextLessThanPreviousAtt)));
            Throws <ArgumentException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumNegativeApplies)));

            Throws <CustomAttributeFormatException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumNegativeScale)));
            Throws <CustomAttributeFormatException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumNegativeRounding)));
            Throws <CustomAttributeFormatException>(() => MetricUnitScale.FromEnumValues(typeof(MetricEnumRoundingTooLarge)));
        }
        private static MetricRange AssertAssertRoundtripInvariant(
            long i,
            MetricRange lastRange,
            MetricUnitScale unitScale)
        {
            // best applicable unit
            var unit = unitScale[i];

            // new ranges
            var newRange    = MetricValueHelpers.CreateMetricRange(i, i);
            var minMaxRange = lastRange.Union(newRange);

            AssertRoundtripInvariant(newRange, lastRange, unit);
            AssertRoundtripInvariant(newRange, minMaxRange, unit);
            AssertRoundtripInvariant(lastRange, minMaxRange, unit);

            return(newRange.ContainsWithRounding(lastRange, unit) ? lastRange : newRange);
        }
예제 #7
0
        public static void TestMetricUnitScaleFiveThousands()
        {
            var scale = MetricUnitScale.FromEnumValues(typeof(MetricEnumOk));
            var unit  = scale[4900];

            AreSame(unit, scale[MetricEnumOk.FiveThousands]);
            AreSame(unit, scale["x5K"]);
            AreNotSame(unit, scale[4899.9999]);
            AreSame(unit, scale[5000]);
            AreSame(unit, scale[11505]);
            AreSame(unit, scale[-33000]);
            AreSame(unit, scale[new MetricRange(-20000, 10000)]);
            AreSame(unit, scale[new MetricRange(MetricRange.FromNegativeInfinity, 6543.21)]);
            IsFalse(unit.IsEmpty);
            AreEqual(unit.EnumValue, MetricEnumOk.FiveThousands);
            AreEqual(unit.AppliesFrom, 4900);
            AreEqual(unit.ScaleCoefficient, 5000);
            AreEqual(unit.RoundingDigits, 0);
            AreEqual(unit.DisplayName, "x5K");
        }
예제 #8
0
        public static void TestMetricUnitScaleThousands()
        {
            var scale = MetricUnitScale.FromEnumValues(typeof(MetricEnumOk));
            var unit  = scale[900];

            AreSame(unit, scale[MetricEnumOk.Thousands]);
            AreSame(unit, scale["k"]);
            AreNotSame(unit, scale[899.9999]);
            AreSame(unit, scale[1000]);
            AreSame(unit, scale[1505]);
            AreSame(unit, scale[-1505]);
            AreSame(unit, scale[new MetricRange(-10000, 900)]);
            AreSame(unit, scale[new MetricRange(MetricRange.FromNegativeInfinity, 907)]);
            IsFalse(unit.IsEmpty);
            AreEqual(unit.EnumValue, MetricEnumOk.Thousands);
            AreEqual(unit.AppliesFrom, 900);
            AreEqual(unit.ScaleCoefficient, 1000);
            AreEqual(unit.RoundingDigits, null);
            AreEqual(unit.DisplayName, "K");
        }
예제 #9
0
        public static void TestMetricUnitScaleMillions()
        {
            var m     = 1000 * 1000;
            var scale = MetricUnitScale.FromEnumValues(typeof(MetricEnumOk));
            var unit  = scale[m];

            AreSame(unit, scale[MetricEnumOk.Millions]);
            AreSame(unit, scale["M"]);
            AreNotSame(unit, scale[0.99 * m]);
            AreSame(unit, scale[-2 * m]);
            AreSame(unit, scale[double.NegativeInfinity]);
            AreSame(unit, scale[double.PositiveInfinity]);
            AreSame(unit, scale[MetricRange.Infinite]);
            AreSame(unit, scale[new MetricRange(-4 * m, 1 * m)]);
            IsFalse(unit.IsEmpty);
            AreEqual(unit.EnumValue, MetricEnumOk.Millions);
            AreEqual(unit.AppliesFrom, m);
            AreEqual(unit.ScaleCoefficient, m);
            AreEqual(unit.RoundingDigits, null);
            AreEqual(unit.DisplayName, "M");
        }
예제 #10
0
        public static void TestMetricUnitScaleTens()
        {
            var scale = MetricUnitScale.FromEnumValues(typeof(MetricEnumOk));
            var unit  = scale[8];

            AreSame(unit, scale[MetricEnumOk.Tens]);
            AreSame(unit, scale["* 10"]);
            AreNotSame(unit, scale[7.9999]);
            AreSame(unit, scale[10]);
            AreSame(unit, scale[505]);
            AreSame(unit, scale[-505]);
            AreNotSame(unit, scale[double.NaN]);
            AreSame(unit, scale[new MetricRange(-10, MetricRange.ToPositiveInfinity)]);
            AreSame(unit, scale[new MetricRange(MetricRange.FromNegativeInfinity, 12)]);
            IsFalse(unit.IsEmpty);
            AreEqual(unit.EnumValue, MetricEnumOk.Tens);
            AreEqual(unit.AppliesFrom, 8);
            AreEqual(unit.ScaleCoefficient, 10);
            AreEqual(unit.RoundingDigits, 15);
            AreEqual(unit.DisplayName, "* 10");
        }
        public static void TestContainsWithRounding()
        {
            var unitScale = MetricUnitScale.FromEnumValues(typeof(Distance));

            var valueX = 1002;
            var valueY = 1005;
            var valueZ = 1008;

            var rangeX  = new MetricRange(valueX, valueX);
            var rangeY  = new MetricRange(valueY, valueY);
            var rangeZ  = new MetricRange(valueZ, valueZ);
            var rangeYz = new MetricRange(valueY, valueZ);

            var unit = unitScale[Distance.Meter];

            AssertRoundtripInvariant(rangeY, rangeX, unit);
            AssertRoundtripInvariant(rangeY, rangeZ, unit);
            AssertRoundtripInvariant(rangeY, rangeYz, unit);

            IsFalse(rangeY.ContainsWithRounding(rangeX, unit));
            IsTrue(rangeY.ContainsWithRounding(rangeZ, unit));
            IsTrue(rangeY.ContainsWithRounding(rangeYz, unit));
        }
예제 #12
0
        private static void CheckExecution(ResultAnalysis analysis)
        {
            var summary = analysis.Summary;

            // DONTTOUCH: DO NOT add return into if clauses.
            // All conditions should be checked

            var benchmarksWithReports = summary.Reports
                                        .Where(r => r.ExecuteResults.Any())
                                        .Select(r => r.Benchmark);

            var benchMissing = summary.GetSummaryOrderBenchmarks()
                               .Except(benchmarksWithReports)
                               .Select(b => b.Target.MethodDisplayInfo)
                               .Distinct().
                               ToArray();

            if (benchMissing.Any())
            {
                var benchmarks = benchMissing.Length == 1 ? "benchmark" : "benchmarks";
                analysis.WriteExecutionErrorMessage(
                    $"No result reports for {benchmarks}: {benchMissing.Join(", ")}.",
                    "Ensure that benchmarks were run successfully and did not throw any exceptions.");
            }

            var checksMode = analysis.Options.Checks;

            if (checksMode.CheckMetrics)
            {
                var timeUnits = MetricUnitScale.FromEnumValues(typeof(TimeUnit));

                if (checksMode.TooFastBenchmarkLimit > TimeSpan.Zero)
                {
                    var tooFastReports = GetTargetNames(
                        analysis,
                        r => r.GetResultRuns().Average(run => run.Nanoseconds) < checksMode.TooFastBenchmarkLimit.TotalNanoseconds());

                    if (tooFastReports.Any())
                    {
                        var benchmarks = tooFastReports.Length == 1 ? "Benchmark" : "Benchmarks";
                        var time       = checksMode.TooFastBenchmarkLimit
                                         .TotalNanoseconds()
                                         .ToString(timeUnits);
                        analysis.AddWarningConclusion(
                            $"{benchmarks} {tooFastReports.Join(", ")}: measured run time is less than {time}. " +
                            "Timings are imprecise as they are too close to the timer resolution.",
                            $"Timing limit for this warning is configured via {CompetitionCheckMode.TooFastBenchmarkLimitCharacteristic.FullId}.");
                    }
                }

                if (checksMode.LongRunningBenchmarkLimit > TimeSpan.Zero)
                {
                    var tooSlowReports = GetTargetNames(
                        analysis,
                        r => r.GetResultRuns().Average(run => run.Nanoseconds) > checksMode.LongRunningBenchmarkLimit.TotalNanoseconds());

                    if (tooSlowReports.Any())
                    {
                        var benchmarks = tooSlowReports.Length == 1 ? "Benchmark" : "Benchmarks";
                        var time       = checksMode.LongRunningBenchmarkLimit
                                         .TotalNanoseconds()
                                         .ToString(timeUnits);
                        analysis.AddWarningConclusion(
                            $"{benchmarks} {string.Join(", ", tooSlowReports)}: measured run time is greater than {time}. " +
                            "There's a risk the peak timings were hidden by averages. " +
                            "Consider to reduce the number of iterations performed per each measurement.",
                            $"Timing limit for this warning is configured via {CompetitionCheckMode.LongRunningBenchmarkLimitCharacteristic.FullId}.");
                    }
                }
            }
        }