public async Task CheckIfNeedToTakeSnapshotsAsync() { if (stressUtilOptions.NumIterationsBeforeTotalToTakeBaselineSnapshot > 0 && stressUtilOptions.NumIterations >= stressUtilOptions.NumIterationsBeforeTotalToTakeBaselineSnapshot) { // if we have enough iterations, lets take a snapshot before they're all done so we can compare: take a baseline snapshot if (nSamplesTaken == stressUtilOptions.NumIterations - stressUtilOptions.NumIterationsBeforeTotalToTakeBaselineSnapshot) { baseDumpFileName = await DoCreateDumpAsync($"Taking base snapshot dump at iteration {nSamplesTaken}"); } else if (nSamplesTaken == stressUtilOptions.NumIterations) // final iteration? take snapshot { var filenameMeasurementResults = DumpOutMeasurementsToTxtFile(); Logger.LogMessage($"Measurement Results {filenameMeasurementResults}"); _lstAllLeakResults = (await CalculateLeaksAsync(showGraph: stressUtilOptions.ShowUI, GraphsAsFilePrefix: "Graph")); foreach (var itm in _lstAllLeakResults) { Logger.LogMessage(itm.ToString()); dictTelemetryProperties[$"Ctr{itm.perfCounterData.perfCounterType}rsquared"] = itm.RSquared(); // can't use perfcounter name: invalid property name. so use enum name dictTelemetryProperties[$"Ctr{itm.perfCounterData.perfCounterType}slope"] = itm.slope; dictTelemetryProperties[$"Ctr{itm.perfCounterData.perfCounterType}IsLeak"] = itm.IsLeak; dictTelemetryProperties[$"Ctr{itm.perfCounterData.perfCounterType}Threshold"] = itm.perfCounterData.thresholdRegression; } var lstLeakResults = _lstAllLeakResults.Where(r => r.IsLeak).ToList(); if (lstLeakResults.Count >= 0 || stressUtilOptions.FailTestAsifLeaksFound) { foreach (var leak in lstLeakResults.Where(p => p.IsLeak)) { Logger.LogMessage($"Leak Detected!!!!! {leak}"); } if (lstLeakResults.Count == 0 && stressUtilOptions.FailTestAsifLeaksFound) { Logger.LogMessage($"Failing test even though no leaks found so test artifacts can be examined"); } var currentDumpFile = await DoCreateDumpAsync($"Taking final snapshot dump at iteration {nSamplesTaken}"); if (!string.IsNullOrEmpty(baseDumpFileName)) { _oDumpAnalyzer = new DumpAnalyzer(Logger); var sb = new StringBuilder(); sb.AppendLine($"'{TestName}' Leaks Found"); foreach (var leak in lstLeakResults) { sb.AppendLine($"Leak Detected: {leak}"); } sb.AppendLine(); _oDumpAnalyzer.GetDiff(sb, baseDumpFileName, currentDumpFile, stressUtilOptions.NumIterations, stressUtilOptions.NumIterationsBeforeTotalToTakeBaselineSnapshot, stressUtilOptions.TypesToReportStatisticsOn, out DumpAnalyzer.TypeStatistics baselineTypeStatistics, out DumpAnalyzer.TypeStatistics currentTypeStatistics); if (baselineTypeStatistics != null) { dictTelemetryProperties["TypeStatsExclusiveRetainedBytes_Base"] = baselineTypeStatistics.ExclusiveRetainedBytes; dictTelemetryProperties["TypeStatsInclusiveRetainedBytes_Base"] = baselineTypeStatistics.InclusiveRetainedBytes; } if (currentTypeStatistics != null) { dictTelemetryProperties["TypeStatsExclusiveRetainedBytes_Final"] = currentTypeStatistics.ExclusiveRetainedBytes; dictTelemetryProperties["TypeStatsInclusiveRetainedBytes_Final"] = currentTypeStatistics.InclusiveRetainedBytes; } var fname = Path.Combine(ResultsFolder, $"{DiffFileName}_{nSamplesTaken}.txt"); File.WriteAllText(fname, sb.ToString()); if (stressUtilOptions.ShowUI) { Process.Start(fname); } lstFileResults.Add(new FileResultsData() { filename = fname, description = $"Differences for Type and String counts at iter {nSamplesTaken}" }); Logger.LogMessage("DumpDiff Analysis " + fname); } else { Logger.LogMessage($"No baseline dump: not enough iterations"); } if (this.testContext != null) { if (lstLeakResults.Count > 0) { throw new LeakException($"Leaks found: " + string.Join(",", lstLeakResults.Select(t => t.perfCounterData.perfCounterType).ToList()), lstLeakResults); //Leaks found: GCBytesInAllHeaps,ProcessorPrivateBytes,ProcessorVirtualBytes,KernelHandleCount } } } } } }