void OnOpenInducedStacks(object sender, RoutedEventArgs e) { StackSourceBuilder builder = new StackSourceBuilder(m_traceLog); List <Stats.GCEvent> events = m_gcProcess.Events; for (int i = 0; i < events.Count; i++) { Stats.GCEvent ev = events[i]; if (ev.IsInduced()) { GcEventExtra extra = GetGcEventExtra(ev.GCNumber, false); if (extra != null) { builder.AddSample(extra.GCStartThread, ev.PauseDurationMSec, ev.GCStartRelativeMSec, String.Format("StartGC({0}, {1}, G{2})", ev.Reason, ev.Type, ev.GCGeneration), extra.GCStartIndex); } } } StackSource source = builder.Stacks; if (source.SampleIndexLimit == 0) { MessageBox.Show("No stacks found for induced GC", ".Net Heap Analyzer", MessageBoxButton.OK); } else { StackWindow stackWindow = null; m_dataFile.StackWindowTo(null, ref stackWindow, source, "Induced GC", FirstEventTime, LastEventTime); } }
public List <Issue> GetIssues() { m_issues = new List <Issue>(); if (m_gcProcess.Total.TotalAllocatedMB == 0) { AddIssue(IssueType.Profiling, "No .Net heap allocation found.", "Turn on Clr/ClrPrivate ETW event providers and profile again."); } if (m_allocSites.Count == 0) { AddIssue(IssueType.Profiling, "No .Net allocation tick event found.", "Turn on Clr allocation tick event and profile again."); } if (m_gcProcess.ProcessCpuMSec == 0) { AddIssue(IssueType.Profiling, "No CPU sample event found.", "Turn on CPU sample event and profile again."); } else { double gcCpu = m_gcProcess.Total.TotalGCCpuMSec * 100.0 / m_gcProcess.ProcessCpuMSec; if (gcCpu >= 40) { AddIssue(IssueType.Cpu, String.Format("GC CPU usage extremely high ({0:N1} %)", gcCpu), "Check memory allocation, fragmentation, data structure, object refereence"); } else if (gcCpu >= 10) { AddIssue(IssueType.Cpu, String.Format("GC CPU usage higher than normal ({0:N1} %)", gcCpu), "Check memory allocation, fragmentation, data structure, object refereence"); } } List <Stats.GCEvent> events = m_gcProcess.Events; for (int i = 0; i < events.Count; i++) { Stats.GCEvent e = events[i]; if (e.IsInduced()) { m_induced++; m_inducedPause += e.PauseDurationMSec; } if (e.IsAllocLarge()) { m_allocLarge++; m_allocLargePause += e.PauseDurationMSec; } } if (m_induced != 0) { AddIssue( IssueType.Cpu, String.Format("There are {0:N0} induced GCs, causing total {1:N3} ms pause", m_induced, m_inducedPause), "Check call stack to figure out who is inducing GC"); m_issue.Action = "Induced GC Stacks"; m_issue.OnClick = OnOpenInducedStacks; } if (m_allocLarge != 0) { AddIssue( IssueType.Cpu, String.Format("There are {0:N0} large object GCs, causing total {1:N3} ms pause", m_allocLarge, m_allocLargePause), "Check call stacks to find LOH allocations"); m_issue.Action = "LOH Allocation Stacks"; m_issue.OnClick = OnOpenLargeAllocStacks; } return(m_issues); }