Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement JitInfo API #55046

Merged
merged 22 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\TypeDependencyAttribute.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\DependentHandle.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\GCSettings.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\JitInfo.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumerable.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumerator.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\InteropServices\DynamicInterfaceCastableHelpers.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,12 +349,6 @@ private static unsafe void DispatchTailCalls(
}
}
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern long GetILBytesJitted();

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern int GetMethodsJittedCount();
}
// Helper class to assist with unsafe pinning of arbitrary objects.
// It's used by VM code.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Internal.Runtime.CompilerServices;

namespace System.Runtime
{
public static partial class JitInfo
josalem marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// Get the number of bytes of IL that have been compiled. If <paramref name="currentThread"/> is true,
/// then this value is scoped to the current thread, otherwise, this is a global value.
/// </summary>
/// <param name="currentThread">Whether the returned value should be specific to the current thread. Default: false</param>
/// <returns>The number of bytes of IL the JIT has compiled.</returns>
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern long GetCompiledILBytes(bool currentThread = false);

/// <summary>
/// Get the number of methods that have been compiled. If <paramref name="currentThread"/> is true,
/// then this value is scoped to the current thread, otherwise, this is a global value.
/// </summary>
/// <param name="currentThread">Whether the returned value should be specific to the current thread. Default: false</param>
/// <returns>The number of methods the JIT has compiled.</returns>
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern int GetCompiledMethodCount(bool currentThread = false);
josalem marked this conversation as resolved.
Show resolved Hide resolved

[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern long GetCompilationTimeInTicks(bool currentThread = false);
josalem marked this conversation as resolved.
Show resolved Hide resolved
}
}
9 changes: 7 additions & 2 deletions src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -834,6 +834,12 @@ FCFuncStart(gInterlockedFuncs)
QCFuncElement("_MemoryBarrierProcessWide", COMInterlocked::MemoryBarrierProcessWide)
FCFuncEnd()

FCFuncStart(gJitInfoFuncs)
FCFuncElement("GetCompiledILBytes", GetCompiledILBytes)
FCFuncElement("GetCompiledMethodCount", GetCompiledMethodCount)
FCFuncElement("GetCompilationTimeInTicks", GetCompilationTimeInTicks)
FCFuncEnd()

FCFuncStart(gVarArgFuncs)
FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_IntPtr_PtrVoid_RetVoid, VarArgsNative::Init2)
FCFuncElementSig(COR_CTOR_METHOD_NAME, &gsig_IM_IntPtr_RetVoid, VarArgsNative::Init)
Expand Down Expand Up @@ -879,8 +885,6 @@ FCFuncStart(gRuntimeHelpers)
QCFuncElement("AllocateTypeAssociatedMemory", RuntimeTypeHandle::AllocateTypeAssociatedMemory)
FCFuncElement("AllocTailCallArgBuffer", TailCallHelp::AllocTailCallArgBuffer)
FCFuncElement("GetTailCallInfo", TailCallHelp::GetTailCallInfo)
FCFuncElement("GetILBytesJitted", GetJittedBytes)
FCFuncElement("GetMethodsJittedCount", GetJittedMethodsCount)
FCFuncEnd()

FCFuncStart(gMngdFixedArrayMarshalerFuncs)
Expand Down Expand Up @@ -1158,6 +1162,7 @@ FCClassElement("IReflect", "System.Reflection", gStdMngIReflectFuncs)
FCClassElement("InterfaceMarshaler", "System.StubHelpers", gInterfaceMarshalerFuncs)
#endif
FCClassElement("Interlocked", "System.Threading", gInterlockedFuncs)
FCClassElement("JitInfo", "System.Runtime", gJitInfoFuncs)
#if TARGET_UNIX
FCClassElement("Kernel32", "", gPalKernel32Funcs)
#endif
Expand Down
35 changes: 31 additions & 4 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,33 @@ GARY_IMPL(VMHELPDEF, hlpDynamicFuncTable, DYNAMIC_CORINFO_HELP_COUNT);

uint64_t g_cbILJitted = 0;
uint32_t g_cMethodsJitted = 0;
int64_t g_cQPCTicksInJit = 0;
thread_local uint64_t g_cbILJittedForThread = 0;
thread_local uint32_t g_cMethodsJittedForThread = 0;
thread_local int64_t g_cQPCTicksInJitForThread = 0;

#ifndef CROSSGEN_COMPILE
FCIMPL0(INT64, GetJittedBytes)
FCIMPL1(INT64, GetCompiledILBytes, CLR_BOOL currentThread)
{
FCALL_CONTRACT;

return g_cbILJitted;
return currentThread ? g_cbILJittedForThread : g_cbILJitted;
}
FCIMPLEND

FCIMPL0(INT32, GetJittedMethodsCount)
FCIMPL1(INT32, GetCompiledMethodCount, CLR_BOOL currentThread)
{
FCALL_CONTRACT;

return g_cMethodsJitted;
return currentThread ? g_cMethodsJittedForThread : g_cMethodsJitted;
}
FCIMPLEND

FCIMPL1(INT64, GetCompilationTimeInTicks, CLR_BOOL currentThread)
{
FCALL_CONTRACT;

return currentThread ? g_cQPCTicksInJitForThread : g_cQPCTicksInJit;
}
FCIMPLEND
#endif
Expand Down Expand Up @@ -13030,9 +13042,14 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config,
MethodDesc* ftn = nativeCodeVersion.GetMethodDesc();

PCODE ret = NULL;
LARGE_INTEGER jitStartTimestamp;
LARGE_INTEGER jitEndTimestamp;
int64_t jitTimeQPCTicks = 0;

COOPERATIVE_TRANSITION_BEGIN();

QueryPerformanceCounter(&jitStartTimestamp);

#ifdef FEATURE_PREJIT

if (g_pConfig->RequireZaps() == EEConfig::REQUIRE_ZAPS_ALL &&
Expand Down Expand Up @@ -13394,8 +13411,18 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config,
printf(".");
#endif // _DEBUG

QueryPerformanceCounter(&jitEndTimestamp);

jitTimeQPCTicks = static_cast<int64_t>(jitEndTimestamp.QuadPart - jitStartTimestamp.QuadPart);

FastInterlockExchangeAddLong((LONG64*)&g_cQPCTicksInJit, jitTimeQPCTicks);
g_cQPCTicksInJitForThread += jitTimeQPCTicks;

FastInterlockExchangeAddLong((LONG64*)&g_cbILJitted, methodInfo.ILCodeSize);
g_cbILJittedForThread += methodInfo.ILCodeSize;

FastInterlockIncrement((LONG*)&g_cMethodsJitted);
g_cMethodsJittedForThread++;

COOPERATIVE_TRANSITION_END();
return ret;
Expand Down
5 changes: 3 additions & 2 deletions src/coreclr/vm/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1157,8 +1157,9 @@ CORJIT_FLAGS GetDebuggerCompileFlags(Module* pModule, CORJIT_FLAGS flags);

bool __stdcall TrackAllocationsEnabled();

FCDECL0(INT64, GetJittedBytes);
FCDECL0(INT32, GetJittedMethodsCount);
FCDECL1(INT64, GetCompiledILBytes, CLR_BOOL currentThread);
FCDECL1(INT32, GetCompiledMethodCount, CLR_BOOL currentThread);
FCDECL1(INT64, GetCompilationTimeInTicks, CLR_BOOL currentThread);

#endif // JITINTERFACE_H

Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector64_1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\Vector64DebugView_1.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Intrinsics\X86\Enums.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\JitInfo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Loader\AssemblyLoadContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\Loader\LibraryNameVariation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ namespace System.Diagnostics
{
public partial class Stopwatch
{
private static long QueryPerformanceFrequency()
internal static long QueryPerformanceFrequency()
{
const long SecondsToNanoSeconds = 1000000000;
return SecondsToNanoSeconds;
}

private static long QueryPerformanceCounter()
internal static long QueryPerformanceCounter()
{
return (long)Interop.Sys.GetTimestamp();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace System.Diagnostics
{
public partial class Stopwatch
{
private static unsafe long QueryPerformanceFrequency()
internal static unsafe long QueryPerformanceFrequency()
{
long resolution;

Expand All @@ -16,7 +16,7 @@ private static unsafe long QueryPerformanceFrequency()
return resolution;
}

private static unsafe long QueryPerformanceCounter()
internal static unsafe long QueryPerformanceCounter()
{
long timestamp;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ internal sealed partial class RuntimeEventSource : EventSource
private PollingCounter? _assemblyCounter;
private PollingCounter? _ilBytesJittedCounter;
private PollingCounter? _methodsJittedCounter;
private IncrementingPollingCounter? _jitTimeCounter;

public static void Initialize()
{
Expand Down Expand Up @@ -83,8 +84,9 @@ protected override void OnEventCommand(EventCommandEventArgs command)
_lohSizeCounter ??= new PollingCounter("loh-size", this, () => GC.GetGenerationSize(3)) { DisplayName = "LOH Size", DisplayUnits = "B" };
_pohSizeCounter ??= new PollingCounter("poh-size", this, () => GC.GetGenerationSize(4)) { DisplayName = "POH (Pinned Object Heap) Size", DisplayUnits = "B" };
_assemblyCounter ??= new PollingCounter("assembly-count", this, () => System.Reflection.Assembly.GetAssemblyCount()) { DisplayName = "Number of Assemblies Loaded" };
_ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.CompilerServices.RuntimeHelpers.GetILBytesJitted()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" };
_methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.CompilerServices.RuntimeHelpers.GetMethodsJittedCount()) { DisplayName = "Number of Methods Jitted" };
_ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.JitInfo.GetCompiledILBytes()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" };
_methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.JitInfo.GetCompiledMethodCount()) { DisplayName = "Number of Methods Jitted" };
_jitTimeCounter ??= new IncrementingPollingCounter("time-in-jit", this, () => System.Runtime.JitInfo.GetCompilationTime().TotalMilliseconds) { DisplayName = "Time spent in JIT", DisplayUnits = "ms", DisplayRateTimeScale = new TimeSpan(0, 0, 1) };
}

}
Expand Down
32 changes: 32 additions & 0 deletions src/libraries/System.Private.CoreLib/src/System/Runtime/JitInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Runtime
{
public static partial class JitInfo
{
private const long TicksPerMillisecond = 10000;
private const long TicksPerSecond = TicksPerMillisecond * 1000;

// "Frequency" stores the frequency of the high-resolution performance counter,
// if one exists. Otherwise it will store TicksPerSecond.
// The frequency cannot change while the system is running,
// so we only need to initialize it once.
public static readonly long Frequency = System.Diagnostics.Stopwatch.QueryPerformanceFrequency();
josalem marked this conversation as resolved.
Show resolved Hide resolved
josalem marked this conversation as resolved.
Show resolved Hide resolved

// pre calculating the tick frequency for quickly converting from QPC ticks to DateTime ticks
private static readonly double s_tickFrequency = (double)TicksPerSecond / Frequency;

/// <summary>
/// Get the amount of time the JIT Compiler has spent compiling methods. If <paramref name="currentThread"/> is true,
/// then this value is scoped to the current thread, otherwise, this is a global value.
/// </summary>
/// <param name="currentThread">Whether the returned value should be specific to the current thread. Default: false</param>
/// <returns>The amount of time the JIT Compiler has spent compiling methods.</returns>
public static TimeSpan GetCompilationTime(bool currentThread = false)
{
// See System.Diagnostics.Stopwatch.GetElapsedDateTimeTicks()
return TimeSpan.FromTicks((long)(GetCompilationTimeInTicks(currentThread) * s_tickFrequency));
josalem marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@
<Compile Include="$(BclSourcesRoot)\System\Resources\ManifestBasedResourceGroveler.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\DependentHandle.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\GCSettings.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\JitInfo.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\JitHelpers.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.Mono.cs" />
<Compile Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeFeature.Mono.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ internal enum RuntimeCounters
GC_LARGE_OBJECT_SIZE_BYTES,
GC_LAST_PERCENT_TIME_IN_GC,
JIT_IL_BYTES_JITTED,
JIT_METHODS_JITTED
JIT_METHODS_JITTED,
JIT_TICKS_IN_JIT
}

#if FEATURE_PERFTRACING
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,6 @@ public static object GetUninitializedObject(
return GetUninitializedObjectInternal(new RuntimeTypeHandle(rt).Value);
}

internal static long GetILBytesJitted()
{
return (long)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.JIT_IL_BYTES_JITTED);
}

internal static int GetMethodsJittedCount()
{
return (int)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.JIT_METHODS_JITTED);
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern unsafe void PrepareMethod(IntPtr method, IntPtr* instantiations, int ninst);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.Tracing;

namespace System.Runtime
{
public static partial class JitInfo
{
/// <summary>
/// Get the number of bytes of IL that have been compiled. If <paramref name="currentThread"/> is true,
/// then this value is scoped to the current thread, otherwise, this is a global value.
/// </summary>
/// <param name="currentThread">Whether the returned value should be specific to the current thread. Default: false</param>
/// <returns>The number of bytes of IL the JIT has compiled.</returns>
public static long GetCompiledILBytes(bool currentThread = false)
{
return currentThread ? 0 : (long)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.JIT_IL_BYTES_JITTED);
}

/// <summary>
/// Get the number of methods that have been compiled. If <paramref name="currentThread"/> is true,
/// then this value is scoped to the current thread, otherwise, this is a global value.
/// </summary>
/// <param name="currentThread">Whether the returned value should be specific to the current thread. Default: false</param>
/// <returns>The number of methods the JIT has compiled.</returns>
public static int GetCompiledMethodCount(bool currentThread = false)
{
return currentThread ? 0 : (int)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.JIT_METHODS_JITTED);
}

public static long GetCompilationTimeInTicks(bool currentThread = false)
{
return currentThread ? 0 : (long)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.JIT_TICKS_IN_JIT);
}
}
}
Loading