public GraphWin(MeasurementHolder measurementHolder) { InitializeComponent(); this.DataContext = this; this.measurementHolder = measurementHolder; this.Title = $"{this.measurementHolder.TestName} #Iter = {measurementHolder.stressUtilOptions.NumIterations}"; this.WindowState = WindowState.Maximized; this.Loaded += GraphWin_Loaded; }
private static void DoIterationsFinished(MeasurementHolder measurementHolder, Exception exception) { if (measurementHolder != null) { if (measurementHolder.testContext != null) { measurementHolder.testContext.Properties[PropNameMeasurementHolder] = null; } if (exception != null) { measurementHolder.Logger.LogMessage(exception.ToString()); if (exception is LeakException) { measurementHolder.dictTelemetryProperties["LeakException"] = exception.Message; } else { measurementHolder.dictTelemetryProperties["TestException"] = exception.ToString(); } } measurementHolder.dictTelemetryProperties["TestPassed"] = exception == null; measurementHolder.Dispose(); // write test results } }
/// <summary> /// Iterate the test method the desired number of times /// The call can be made from the TestInitialize or the beginning of the TestMethod /// </summary> /// <param name="test">pass the test itself</param> /// <param name="stressUtilOptions">If passed, includes all options: all other optional parameters are ignored</param> /// <param name="NumIterations">The number of iterations (defaults to 71)</param> public static async Task DoIterationsAsync( object test, StressUtilOptions stressUtilOptions = null, int NumIterations = 71) { MeasurementHolder measurementHolder = null; try { if (stressUtilOptions == null) { stressUtilOptions = new StressUtilOptions() { NumIterations = NumIterations }; } if (!await stressUtilOptions.SetTest(test)) // are we recurring? { return; } measurementHolder = new MeasurementHolder( stressUtilOptions.testContext, stressUtilOptions, SampleType.SampleTypeIteration); var baseDumpFileName = string.Empty; stressUtilOptions.testContext.Properties[PropNameCurrentIteration] = 0; stressUtilOptions.testContext.Properties[PropNameMeasurementHolder] = measurementHolder; var utilFileName = typeof(StressUtil).Assembly.Location; var verInfo = FileVersionInfo.GetVersionInfo(utilFileName); /* * InternalName: Microsoft.Test.Stress.dll * OriginalFilename: Microsoft.Test.Stress.dll * FileVersion: 1.1.29.55167 * FileDescription: Microsoft.Test.Stress * Product: Microsoft.Test.Stress * ProductVersion: 1.1.29+g7fd76485e3 * Debug: False * Patched: False * PreRelease: False * PrivateBuild: False * SpecialBuild: False * Language: Language Neutral */ stressUtilOptions.logger.LogMessage($"{utilFileName} {verInfo.OriginalFilename} FileVersion:{verInfo.FileVersion} ProductVesion:{verInfo.ProductVersion}"); measurementHolder.dictTelemetryProperties["StressLibVersion"] = verInfo.FileVersion; for (int iteration = 0; iteration < stressUtilOptions.NumIterations; iteration++) { if (stressUtilOptions.actExecuteBeforeEveryIterationAsync != null) { await stressUtilOptions.actExecuteBeforeEveryIterationAsync(iteration + 1, measurementHolder); } var result = stressUtilOptions._theTestMethod.Invoke(test, parameters: null); if (stressUtilOptions._theTestMethod.ReturnType.Name == "Task") { var resultTask = (Task)result; await resultTask; } var res = await measurementHolder.TakeMeasurementAsync($"Iter {iteration + 1,3}/{stressUtilOptions.NumIterations}", DoForceGC : true); stressUtilOptions.logger.LogMessage(res); stressUtilOptions.testContext.Properties[PropNameCurrentIteration] = (int)(stressUtilOptions.testContext.Properties[PropNameCurrentIteration]) + 1; } // note: if a leak is found an exception will be throw and this will not get called // increment one last time, so test methods can check for final execution after measurements taken stressUtilOptions.testContext.Properties[PropNameCurrentIteration] = (int)(stressUtilOptions.testContext.Properties[PropNameCurrentIteration]) + 1; DoIterationsFinished(measurementHolder, exception: null); } catch (Exception ex) { DoIterationsFinished(measurementHolder, ex); throw; } }
public async Task WaitTilVSQuietAsync(int circBufferSize = 5, int numTimesToGetQuiet = 50) { var measurementHolder = this; // we want to take measures in a circular buffer and wait til those are quiet var quietMeasure = new MeasurementHolder( "Quiet", new StressUtilOptions() { SendTelemetry = false, // we don't want the inner MeasurementHolder to send telemetry NumIterations = 1, // we'll do 1 iteration pctOutliersToIgnore = 0, logger = measurementHolder.Logger, VSHandler = measurementHolder.stressUtilOptions.VSHandler, lstPerfCountersToUse = measurementHolder.stressUtilOptions.lstPerfCountersToUse, }, SampleType.SampleTypeIteration ); // We just took a measurement, so copy those values to init our buffer foreach (var pctrMeasure in measurementHolder.measurements.Keys) { var lastVal = measurementHolder.measurements[pctrMeasure][measurementHolder.nSamplesTaken - 1]; quietMeasure.measurements[pctrMeasure].Add(lastVal); } quietMeasure.nSamplesTaken++; var isQuiet = false; int nMeasurementsForQuiet = 0; while (!isQuiet && nMeasurementsForQuiet < numTimesToGetQuiet) { await quietMeasure.DoForceGCAsync(); await Task.Delay(TimeSpan.FromSeconds(1 * measurementHolder.stressUtilOptions.DelayMultiplier)); // after GC, wait 1 before taking measurements var sb = new StringBuilder($"Measure for Quiet iter = {measurementHolder.nSamplesTaken} QuietSamp#= {nMeasurementsForQuiet}"); quietMeasure.TakeRawMeasurement(sb); //measurementHolder.Logger.LogMessage(sb.ToString());//xxxremove if (quietMeasure.nSamplesTaken == circBufferSize) { var lk = await quietMeasure.CalculateLeaksAsync( showGraph : false, GraphsAsFilePrefix : #if DEBUG "Graph" #else null #endif ); isQuiet = true; foreach (var k in lk.Where(p => !p.IsQuiet())) { //measurementHolder.Logger.LogMessage($" !quiet {k}"); //xxxremove isQuiet = false; } // isQuiet = !lk.Where(k => !k.IsQuiet()).Any(); foreach (var pctrMeasure in quietMeasure.measurements.Keys) // circular buffer: remove 1st item { quietMeasure.measurements[pctrMeasure].RemoveAt(0); } quietMeasure.nSamplesTaken--; } nMeasurementsForQuiet++; } this._GoneQuietSamplesTaken += nMeasurementsForQuiet; // for avg calc this._IterationsGoneQuiet++; // for total # gone quiet if (isQuiet) // the counters have stabilized. We'll use the stabilized numbers as the sample value for the iteration { measurementHolder.Logger.LogMessage($"Gone quiet in {nMeasurementsForQuiet} measures"); } else { measurementHolder.Logger.LogMessage($"Didn't go quiet in {numTimesToGetQuiet}"); } // Whether or not it's quiet, we'll take the most recent measure as the iteration sample foreach (var pctrMeasure in measurementHolder.measurements.Keys) { var lastVal = quietMeasure.measurements[pctrMeasure][quietMeasure.nSamplesTaken - 1]; measurementHolder.measurements[pctrMeasure][measurementHolder.nSamplesTaken - 1] = lastVal; } }