Skip to content

Instantly share code, notes, and snippets.

@noahfalk
Created May 19, 2020 02:21
Show Gist options
  • Save noahfalk/935e43bf69e3737f55164ac16f2d2ee6 to your computer and use it in GitHub Desktop.
Save noahfalk/935e43bf69e3737f55164ac16f2d2ee6 to your computer and use it in GitHub Desktop.

Revisions

  1. noahfalk created this gist May 19, 2020.
    88 changes: 88 additions & 0 deletions Program.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    using Microsoft.Diagnostics.NETCore.Client;
    using Microsoft.Diagnostics.Tracing;
    using Microsoft.Diagnostics.Tracing.Analysis;
    using Microsoft.Diagnostics.Tracing.Analysis.GC;
    using Microsoft.Diagnostics.Tracing.Parsers.Clr;
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Diagnostics.Tracing;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Threading.Tasks;

    namespace SampleApp
    {
    class Program
    {
    static List<object> s_objects = new List<object>();

    static void Main(string[] args)
    {
    GCEventPipeMonitor monitor = new GCEventPipeMonitor();
    monitor.Start();
    Task.Run(AllocateMemory);
    Console.ReadLine();
    }

    static void AllocateMemory()
    {
    while(true)
    {
    s_objects.Add(new byte[50_000]);
    Thread.Sleep(10);
    }
    }
    }


    public class GCEventPipeMonitor
    {
    DiagnosticsClient _client;
    EventPipeSession _session;
    public void Start()
    {
    Task.Run(() =>
    {
    int pid = Process.GetCurrentProcess().Id;
    _client = new DiagnosticsClient(pid);
    _session = _client.StartEventPipeSession(new EventPipeProvider[]
    {
    new EventPipeProvider("Microsoft-Windows-DotNETRuntime", EventLevel.Informational, 0x1)
    },
    requestRundown: false,
    circularBufferMB: 5);
    EventPipeEventSource source = new EventPipeEventSource(_session.EventStream);
    source.NeedLoadedDotNetRuntimes();
    source.AddCallbackOnProcessStart(delegate (TraceProcess proc)
    {
    proc.AddCallbackOnDotNetRuntimeLoad(delegate (TraceLoadedDotNetRuntime runtime)
    {
    runtime.GCEnd += delegate (TraceProcess p, TraceGC gc)
    {
    Console.WriteLine($"GC#{gc.Number} Gen2 Fragmentation is: {gc.GenFragmentationPercent(Gens.Gen2):g2}%");
    };
    });
    });
    source.Process();
    });
    }
    }
    }

    /* Example output
    GC#1 Gen2 Fragmentation is: 0%
    GC#2 Gen2 Fragmentation is: 3.9%
    GC#3 Gen2 Fragmentation is: 0%
    GC#5 Gen2 Fragmentation is: 1.9%
    GC#4 Gen2 Fragmentation is: 1.9%
    GC#6 Gen2 Fragmentation is: 0%
    GC#7 Gen2 Fragmentation is: 1.2%
    GC#8 Gen2 Fragmentation is: 0%
    GC#9 Gen2 Fragmentation is: 0.9%
    GC#10 Gen2 Fragmentation is: 0%
    GC#12 Gen2 Fragmentation is: 0.74%
    GC#11 Gen2 Fragmentation is: 0.77%
    GC#13 Gen2 Fragmentation is: 0%
    GC#14 Gen2 Fragmentation is: 0.67%
    */