public static IEnumerable <IConcurrencyResults> CollectChildSets(this IConcurrencyResults r) { var all = r.AllRuns().ToArray(); List <IConcurrencyResults> childSets = new List <IConcurrencyResults>(); if (!all.Any(n => n.HasChildren)) { return(childSets); //Return empty set when there are no children; } var setCount = all.Max(n => n.Children.Count()); for (var i = 0; i < setCount; i++) { if (all.Any(ins => ins.Children.Count() != setCount)) { throw new ArgumentOutOfRangeException("All run trees must have identical structure - mismatched children within segment" + r.SegmentName, "runs"); } var childSeq = r.SequentialRuns.Select(instance => instance.Children[i]).ToArray(); var childPar = r.ParallelRuns.Select(instance => instance.Children[i]).ToArray(); var name = (childSeq.FirstOrDefault() ?? childPar.FirstOrDefault()).SegmentName; var child = new ConcurrencyResult(childSeq, childPar, r.ParallelThreads, name); child.Validate(); childSets.Add(child); } return(childSets); }
/// <summary> /// Returns a anonymous timing string for the given set of nodes (non-recursive) /// </summary> /// <param name="runs"></param> /// <returns></returns> public string GetTimingInfo(IConcurrencyResults r) { var sincl = r.SequentialRuns.InclusiveMs(); var sexcl = r.SequentialRuns.ExclusiveMs(); var pincl = r.ParallelRuns.InclusiveMs(); var pexcl = r.ParallelRuns.ExclusiveMs(); var suffix = string.Format(" {0:F}%||", r.GetStats().ParallelConcurrencyPercent); if (r.Invocations().Max > 1) { suffix += string.Format(" calls: {0}", r.Invocations().ToString(0)); } if (sexcl.DeltaRatio > DeltaAbnormalRatio) { var runTimes = r.AllRuns().Select(n => n.TicksExclusiveTotal).ToMilliseconds().Select(m => Math.Round(m)); return(string.Format("runs exclusive: {1} {0}", suffix, String.Join(" ", runTimes))); } else if (r.SequentialRuns.First().HasChildren) { return(string.Format("exclusive: {0} ||{1}|| inclusive: {2} ||{3} {4}", sexcl.ToString(DeltaSignificantRatio), pexcl.ToString(DeltaSignificantRatio), sincl.ToString(DeltaSignificantRatio), pincl.ToString(DeltaSignificantRatio), suffix)); } else { return(string.Format("{0} ||{1} {2}", sincl.ToString(DeltaSignificantRatio), pincl.ToString(DeltaSignificantRatio), suffix));; } }
/// <summary> /// Traverses the tree and grabs a set of matching subtrees with the given segment name. /// </summary> /// <param name="tree"></param> /// <param name="name"></param> /// <returns></returns> public static IConcurrencyResults FindSet(this IConcurrencyResults r, string segmentName = "op", bool expectOnlyOne = true) { var results = FindSets(r, segmentName); if (results.Count() > 1) { throw new ArgumentOutOfRangeException("tree", "More than one matching set found in tree"); } return(results.First()); }
public static string DebugPrintTree(this IConcurrencyResults r) { var f = new ConcurrencyResultFormatter() { DeltaAbnormalRatio = 100, DeltaSignificantRatio = 0, ExclusiveTimeSignificantMs = 0 }; var s = f.PrintCallTree(r); Debug.Write(s); return(s); }
public static SegmentStats GetStats(this IConcurrencyResults r) { var activeWallTime = r.ParallelRuns.DeduplicateTime(); var s = new SegmentStats(); s.SegmentName = r.SegmentName; s.SequentialMs = r.SequentialRuns.InclusiveMs(); s.SequentialExclusiveMs = r.SequentialRuns.ExclusiveMs(); s.ParallelMs = r.ParallelRuns.InclusiveMs(); s.ParallelExclusiveMs = r.ParallelRuns.ExclusiveMs(); s.ParallelThreads = r.ParallelThreads; s.ParallelRealMs = activeWallTime * 1000 / (double)Stopwatch.Frequency; return(s); }
private string PrintStats(IConcurrencyResults r, string prefix = "") { if (r == null || !r.HasRuns()) { return(null); } var sb = new StringBuilder(); if (r.MaxExclusiveMs() >= ExclusiveTimeSignificantMs) { sb.AppendFormat("{0}{1} {2}\n", prefix, r.SegmentName, GetTimingInfo(r)); sb.Append(string.Join("", r.CollectChildSets().Select(s => PrintStats(s, prefix + Indentation)))); } else { sb.Append(string.Join("", r.CollectChildSets().Select(s => PrintStats(s, prefix + r.SegmentName + ">")))); } return(sb.ToString()); }
public static bool HasRuns(this IConcurrencyResults r) { return(r.ParallelRuns.Count() > 0 || r.SequentialRuns.Count() > 0); }
/// <summary> /// Provides an enumerator which traverses the tree (either depth-first or breadth-first) /// </summary> /// <param name="tree"></param> /// <param name="breadthFirst"></param> /// <param name="includeRoot"></param> /// <returns></returns> public static IEnumerable <IConcurrencyResults> Traverse(this IConcurrencyResults tree, bool breadthFirst) { return(tree.TraverseTree(n => n.CollectChildSets(), null, breadthFirst)); }
public static SegmentStats StatsForSegment(this IConcurrencyResults r, string segmentName = "op") { return(FindSet(r, segmentName).GetStats()); }
public static void Validate(this IConcurrencyResults r) { r.AllRuns().ValidateSet("Within " + r.SegmentName); }
public static IEnumerable <IConcurrencyResults> FindSets(this IConcurrencyResults tree, string segmentName = "op") { return(tree.TraverseTree(n => n.CollectChildSets(), c => c.SegmentName == segmentName, true)); }
public static double MaxExclusiveMs(this IConcurrencyResults r) { return(r.AllRuns().Max(n => n.TicksExclusiveTotal) * 1000.0 / (double)Stopwatch.Frequency); }
public static Stat <long> Invocations(this IConcurrencyResults r) { return(r.SequentialRuns.Invocations().Combine(r.ParallelRuns.Invocations())); }
public static double ParallelRealMs(this IConcurrencyResults r) { return(r.GetStats().ParallelRealMs); }
public string PrintCallTree(IConcurrencyResults r) { return(PrintStats(r)); }
public static IConcurrencyResults FindSlowestSegment(this IConcurrencyResults r) { return(r.GetSegmentStatsRecursively().OrderByDescending(p => p.Item2.ParallelExclusiveMs.Avg).First().Item1); }
public static IConcurrencyResults FindLeastConcurrentSegment(this IConcurrencyResults r) { return(r.GetSegmentStatsRecursively().OrderByDescending(p => p.Item2.ParallelConcurrencyPercent).First().Item1); }
public static IEnumerable <Tuple <IConcurrencyResults, SegmentStats> > GetSegmentStatsRecursively(this IConcurrencyResults r) { return(r.Traverse(true).Select(n => new Tuple <IConcurrencyResults, SegmentStats>(n, n.GetStats()))); }
public static IEnumerable <ProfilingResultNode> AllRuns(this IConcurrencyResults r) { return(Enumerable.Concat(r.SequentialRuns, r.ParallelRuns)); }
public static double FastestSequentialMs(this IConcurrencyResults r) { return(r.GetStats().SequentialMs.Min); }