Exemplo n.º 1
0
        private void NotifyCollection(TraceGC gc)
        {
            var listeners = GarbageCollection;

            if (listeners == null)
            {
                return;
            }

            var sizesBefore = GetBeforeGenerationSizes(gc);
            var sizesAfter  = GetAfterGenerationSizes(gc);

            listeners?.Invoke(this, new GarbageCollectionArgs(
                                  _processId,
                                  gc.StartRelativeMSec,
                                  gc.Number,
                                  gc.Generation,
                                  (GarbageCollectionReason)gc.Reason,
                                  (GarbageCollectionType)gc.Type,
                                  !gc.IsNotCompacting(),
                                  gc.HeapStats.GenerationSize0,
                                  gc.HeapStats.GenerationSize1,
                                  gc.HeapStats.GenerationSize2,
                                  gc.HeapStats.GenerationSize3,
                                  sizesBefore,
                                  sizesAfter,
                                  gc.SuspendDurationMSec,
                                  gc.PauseDurationMSec,
                                  gc.BGCFinalPauseMSec
                                  ));
        }
        public void Process(int processId, TraceGC gc)
        {
            var args = mapper.Map(processId, gc);

            foreach (var handler in handlers)
            {
                handler.Handle(args);
            }
        }
Exemplo n.º 3
0
        private static void WriteFormattedTraceGC(TextWriter tw, string prefix, TraceGC gc)
        {
            // Fields are not really obsolete, but experimental.
#pragma warning disable CS0618
            double mbBefore = gc.HeapSizeBeforeMB;
            double mbAfter  = gc.HeapSizeAfterMB;
#pragma warning restore CS0618

            tw.WriteLine("{0}    heap size before {1:N2} MB, after {2:N2} MB, {3:N2} % freed.",
                         prefix, mbBefore, mbAfter,
                         (100 - (((double)mbAfter / mbBefore) * 100)));
        }
Exemplo n.º 4
0
 private void RuntimeGCEnd(TraceProcess traceProcess, TraceGC gc)
 {
     if (traceProcess.ProcessID == _currentProcessId)
     {
         if (!_isMetricAlreadyCaptured)
         {
             lock (_lock)
                 _isMetricAlreadyCaptured = true;
         }
         _gcTimeInTicks = (long)gc.DurationMSec * 10_000;
         _gcCount       = (uint)gc.Number;
     }
 }
        private static long[] GetGenerationSizes(TraceGC gc, bool before)
        {
            var sizes = new long[4];

            if (gc.PerHeapHistories == null)
            {
                return(sizes);
            }

            foreach (var history in gc.PerHeapHistories)
            {
                for (var gen = 0; gen <= 3; gen++)
                {
                    sizes[gen] += before ? history.GenData[gen].ObjSpaceBefore : history.GenData[gen].ObjSizeAfter;
                }
            }

            return(sizes);
        }
Exemplo n.º 6
0
        private int FindEvent(double tick, int start)
        {
            for (int i = start; i < m_heapInfo.GcEvents.Count; i++)
            {
                TraceGC gc = m_heapInfo.GcEvents[i];

                if (tick >= gc.PauseStartRelativeMSec)
                {
                    if (tick < gc.PauseStartRelativeMSec + gc.PauseDurationMSec)
                    {
                        return(i);
                    }
                }
                else
                {
                    break;
                }
            }

            return(-1);
        }
Exemplo n.º 7
0
        private long[] GetGenerationSizes(TraceGC gc, bool before)
        {
            var sizes = new long[4];

            if (gc.PerHeapHistories == null)
            {
                return(sizes);
            }

            for (int heap = 0; heap < gc.PerHeapHistories.Count; heap++)
            {
                // LOH = 3
                for (int gen = 0; gen <= 3; gen++)
                {
                    sizes[gen] += before ?
                                  gc.PerHeapHistories[heap].GenData[gen].ObjSpaceBefore:
                                  gc.PerHeapHistories[heap].GenData[gen].ObjSizeAfter;
                }
            }

            return(sizes);
        }
Exemplo n.º 8
0
        private void OnOpenInducedStacks(object sender, RoutedEventArgs e)
        {
            StackSourceBuilder builder = new StackSourceBuilder(m_traceLog);

            List <TraceGC> events = m_runtime.GC.GCs;

            for (int i = 0; i < events.Count; i++)
            {
                TraceGC ev = events[i];

                if (ev.IsInduced())
                {
                    GcEventExtra extra = GetGcEventExtra(ev.Number, false);

                    if (extra != null)
                    {
                        builder.AddSample(extra.GCStartThread, ev.PauseDurationMSec, ev.StartRelativeMSec,
                                          String.Format("StartGC({0}, {1}, G{2})", ev.Reason, ev.Type, ev.Generation),
                                          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 GarbageCollectionArgs Map(int processId, TraceGC gc)
        {
            var sizesBefore = GetGenerationSizes(gc, true);
            var sizesAfter  = GetGenerationSizes(gc, false);

            return(new GarbageCollectionArgs(
                       processId,
                       gc.StartRelativeMSec,
                       gc.Number,
                       gc.Generation,
                       (GarbageCollectionReason)gc.Reason,
                       (GarbageCollectionType)gc.Type,
                       !gc.IsNotCompacting(),
                       gc.HeapStats.GenerationSize0,
                       gc.HeapStats.GenerationSize1,
                       gc.HeapStats.GenerationSize2,
                       gc.HeapStats.GenerationSize3,
                       sizesBefore,
                       sizesAfter,
                       gc.SuspendDurationMSec,
                       gc.PauseDurationMSec,
                       gc.BGCFinalPauseMSec
                       ));
        }
Exemplo n.º 10
0
        public List <Issue> GetIssues()
        {
            m_issues = new List <Issue>();

            if (m_runtime.GC.Stats().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_process.CPUMSec == 0)
            {
                AddIssue(IssueType.Profiling, "No CPU sample event found.", "Turn on CPU sample event and profile again.");
            }
            else
            {
                double gcCpu = m_runtime.GC.Stats().TotalCpuMSec * 100.0 / m_process.CPUMSec;

                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 <TraceGC> events = m_runtime.GC.GCs;

            for (int i = 0; i < events.Count; i++)
            {
                TraceGC 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);
        }
Exemplo n.º 11
0
 internal GcEventWrapper(TraceGC evnt)
 {
     m_event = evnt;
 }
Exemplo n.º 12
0
        /// <summary>
        /// Filter events according to checkboxes
        /// </summary>
        IEnumerable <GcEventWrapper> FilterEvent()
        {
            bool no_g0    = m_g0.UnChecked();
            bool no_g1    = m_g1.UnChecked();
            bool no_g2Blk = m_g2Blocking.UnChecked();
            bool no_g2Bak = m_g2Background.UnChecked();

            bool no_inducedBlocking = m_inducedBlocking.UnChecked();
            bool no_inducedNonBlock = m_inducedNonblocking.UnChecked();
            bool no_lowMemory       = m_lowMemory.UnChecked();
            bool no_allocSOH        = m_allocSOH.UnChecked();
            bool no_allocLOH        = m_AllocLOH.UnChecked();

            foreach (GcEventWrapper er in m_gcEvents)
            {
                TraceGC e = er.Event;

                GCType typ = e.Type;

                switch (e.Generation)
                {
                case 0:
                    if (no_g0)
                    {
                        continue;
                    }
                    break;

                case 1:
                    if (no_g1)
                    {
                        continue;
                    }
                    break;

                case 2:
                    if (no_g2Blk && (typ == GCType.NonConcurrentGC))
                    {
                        continue;
                    }
                    if (no_g2Bak && (typ == GCType.BackgroundGC))
                    {
                        continue;
                    }
                    break;
                }

                switch (e.Reason)
                {
                case GCReason.OutOfSpaceSOH:
                case GCReason.AllocSmall:
                    if (no_allocSOH)
                    {
                        continue;
                    }
                    break;

                case GCReason.InducedNotForced:
                case GCReason.Induced:
                    if (no_inducedBlocking && (typ == GCType.NonConcurrentGC))
                    {
                        continue;
                    }
                    if (no_inducedNonBlock && (typ == GCType.BackgroundGC))
                    {
                        continue;
                    }
                    break;

                case GCReason.OutOfSpaceLOH:
                case GCReason.AllocLarge:
                    if (no_allocLOH)
                    {
                        continue;
                    }
                    break;

                case GCReason.LowMemory:
                case GCReason.InducedLowMemory:
                    if (no_lowMemory)
                    {
                        continue;
                    }
                    break;

                case GCReason.Empty:
                case GCReason.Internal:
                default:
                    break;
                }

                yield return(er);
            }
        }
Exemplo n.º 13
0
 private static void RuntimeOnGCEnd(TraceProcess p, TraceGC gc)
 {
     Console.WriteLine($"{gc.GCGenerationName} {gc.Reason} {gc.PauseDurationMSec:F2}/{gc.DurationMSec:F2}");
 }
Exemplo n.º 14
0
        private long[] GetAfterGenerationSizes(TraceGC gc)
        {
            var after = false;

            return(GetGenerationSizes(gc, after));
        }
Exemplo n.º 15
0
        private long[] GetBeforeGenerationSizes(TraceGC gc)
        {
            var before = true;

            return(GetGenerationSizes(gc, before));
        }
Exemplo n.º 16
0
 private static void RuntimeOnGCEnd(TraceProcess tp, TraceGC gc)
 {
     Console.WriteLine($"[{DateTime.Now.ToLongTimeString()}] GLAD received from {tp.Name}/{tp.ProcessID}");
     Console.WriteLine($"   {gc.GCGenerationName} {gc.Reason} Pause: {gc.PauseDurationMSec:F2} ms/{gc.DurationMSec:F2} ms");
     Console.WriteLine();
 }