Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AndyAyersMS/2eec28ec22cb0c710111b0b0f7fde689 to your computer and use it in GitHub Desktop.
Save AndyAyersMS/2eec28ec22cb0c710111b0b0f7fde689 to your computer and use it in GitHub Desktop.
Subscribe to jit events
using System;
using System.Diagnostics.Tracing;
using System.Runtime.CompilerServices;
using System.Threading;
class JitEventListener : EventListener
{
const int JitKeyword = 0x00000010;
const int VerboseMethodLoadId = 143;
static bool first = true;
protected override void OnEventSourceCreated(EventSource eventSource)
{
if (eventSource.Name.Equals("Microsoft-Windows-DotNETRuntime"))
{
EnableEvents(
eventSource,
EventLevel.Verbose,
(EventKeywords)(JitKeyword)
);
}
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
if (eventData.EventId == VerboseMethodLoadId)
{
ulong startAddress = 0;
uint size = 0;
string namespaceName = "?";
string methodName = "?";
uint flags = 0;
// see https://docs.microsoft.com/en-us/dotnet/framework/performance/method-etw-events
for (int i = 0; i < eventData.Payload.Count; i++)
{
object payload = eventData.Payload[i];
string payloadName = eventData.PayloadNames[i];
if (payloadName == "MethodStartAddress")
{
startAddress = (ulong)payload;
}
else if (payloadName == "MethodSize")
{
size = (uint)payload;
}
else if (payloadName == "MethodNamespace")
{
namespaceName = (string)payload;
}
else if (payloadName == "MethodName")
{
methodName = (string)payload;
}
else if (payloadName == "MethodFlags")
{
flags = (uint)payload;
}
}
string flagString = "";
if ((flags & 0x8) != 0)
{
flagString += " jitted";
}
else
{
flagString += " prejitted";
}
uint optLevel = ((flags >> 7) & 0x7);
switch (optLevel)
{
case 1: flagString += " minopts"; break;
case 2: flagString += " fullopts"; break;
case 3: flagString += " tier0"; break;
case 4: flagString += " tier1"; break;
case 5: flagString += " tier1-OSR"; break;
default: flagString += " unknown codegen"; break;
}
if (first)
{
Console.WriteLine("{0,-18} {1,-6} {2,-20} {3}", "Address", "Size", "Info", "Name");
first = false;
}
Console.WriteLine($"0x{startAddress:X16} {size:D6}{flagString,-20} {namespaceName}.{methodName}");
}
}
}
class JitEventSample
{
[MethodImpl(MethodImplOptions.NoInlining)]
static int F(int x)
{
return x * x;
}
static void Main(string[] args)
{
_ = new JitEventListener();
var f = F(33);
Console.WriteLine($"F(33) = {f}");
// give event stream a chance to catch up
Thread.Sleep(5_000);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment