Created
May 20, 2020 22:40
-
-
Save AndyAyersMS/2eec28ec22cb0c710111b0b0f7fde689 to your computer and use it in GitHub Desktop.
Subscribe to jit events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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