return GCHeapUtilities::GetGCHeap()->WhichGeneration(obj);
}
+COOP_PINVOKE_HELPER(int64_t, RhGetGenerationSize, (int32_t gen))
+{
+ return (int64_t)(GCHeapUtilities::GetGCHeap()->GetLastGCGenerationSize(gen));
+}
+
+COOP_PINVOKE_HELPER(int64_t, RhGetLastGCPercentTimeInGC, ())
+{
+ return GCHeapUtilities::GetGCHeap()->GetLastGCPercentTimeInGC();
+}
+
+
COOP_PINVOKE_HELPER(int32_t, RhGetGcLatencyMode, ())
{
return GCHeapUtilities::GetGCHeap()->GetGcLatencyMode();
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using System.Threading;
using MethodBase = System.Reflection.MethodBase;
RH_EH_FIRST_RETHROW_FRAME = 2,
}
+ // Performance metric to count the number of exceptions thrown
+ private static uint s_exceptionCount;
+ internal static uint GetExceptionCount() => s_exceptionCount;
+
[RuntimeExport("AppendExceptionStackFrame")]
private static void AppendExceptionStackFrame(object exceptionObj, IntPtr IP, int flags)
{
bool isFirstFrame = (flags & (int)RhEHFrameType.RH_EH_FIRST_FRAME) != 0;
bool isFirstRethrowFrame = (flags & (int)RhEHFrameType.RH_EH_FIRST_RETHROW_FRAME) != 0;
+ // track count for metrics
+ if (isFirstFrame && !isFirstRethrowFrame)
+ Interlocked.Increment(ref s_exceptionCount);
+
// When we're throwing an exception object, we first need to clear its stacktrace with two exceptions:
// 1. Don't clear if we're rethrowing with `throw;`.
// 2. Don't clear if we're throwing through ExceptionDispatchInfo.
return RuntimeImports.RhGetGeneration(obj);
}
+ internal static int GetGenerationSize(int gen)
+ {
+ return RuntimeImports.RhGetGenerationSize(gen);
+ }
+
+ internal static int GetLastGCPercentTimeInGC()
+ {
+ return RuntimeImports.RhGetLastGCPercentTimeInGC();
+ }
+
/// <summary>
/// Returns the current generation number of the target
/// of a specified <see cref="System.WeakReference"/>.
return Load(name);
}
+ // Performance metric to count the number of assemblies
+ // Caching since in NativeAOT, the number will be the same
+ private static uint s_assemblyCount;
+ internal static uint GetAssemblyCount()
+ {
+ if (s_assemblyCount == 0)
+ s_assemblyCount = (uint)Internal.Reflection.Core.Execution.ReflectionCoreExecution.ExecutionDomain.ReflectionDomainSetup.AssemblyBinder.GetLoadedAssemblies().Count;
+ return s_assemblyCount;
+ }
+
[Obsolete("Assembly.LoadWithPartialName has been deprecated. Use Assembly.Load() instead.")]
public static Assembly LoadWithPartialName(string partialName)
{
[RuntimeImport(RuntimeLibrary, "RhGetGeneration")]
internal static extern int RhGetGeneration(object obj);
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [RuntimeImport(RuntimeLibrary, "RhGetGenerationSize")]
+ internal static extern int RhGetGenerationSize(int gen);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [RuntimeImport(RuntimeLibrary, "RhGetLastGCPercentTimeInGC")]
+ internal static extern int RhGetLastGCPercentTimeInGC();
+
[MethodImpl(MethodImplOptions.InternalCall)]
[RuntimeImport(RuntimeLibrary, "RhGetGcLatencyMode")]
internal static extern GCLatencyMode RhGetGcLatencyMode();
using System.Threading;
using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
namespace System.Diagnostics.Tracing
{
private IncrementingPollingCounter? _allocRateCounter;
private PollingCounter? _timerCounter;
private PollingCounter? _fragmentationCounter;
-
-#if !NATIVEAOT // TODO shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
private PollingCounter? _committedCounter;
private IncrementingPollingCounter? _exceptionCounter;
private PollingCounter? _gcTimeCounter;
private PollingCounter? _lohSizeCounter;
private PollingCounter? _pohSizeCounter;
private PollingCounter? _assemblyCounter;
-#endif // !NATIVEAOT
-
private PollingCounter? _ilBytesJittedCounter;
private PollingCounter? _methodsJittedCounter;
private IncrementingPollingCounter? _jitTimeCounter;
+#if NATIVEAOT
+ // If EventSource feature is enabled, RuntimeEventSource needs to be initialized for NativeAOT
+ // In CoreCLR, this is done via StartupHookProvider.CoreCLR.cs
+#pragma warning disable CA2255
+ [ModuleInitializer]
+#pragma warning restore CA2255
+#endif
public static void Initialize()
{
// initializing more than once may lead to missing events
return gcInfo.HeapSizeBytes != 0 ? gcInfo.FragmentedBytes * 100d / gcInfo.HeapSizeBytes : 0;
}) { DisplayName = "GC Fragmentation", DisplayUnits = "%" };
-#if !NATIVEAOT // TODO
_committedCounter ??= new PollingCounter("gc-committed", this, () => ((double)GC.GetGCMemoryInfo().TotalCommittedBytes / 1_000_000)) { DisplayName = "GC Committed Bytes", DisplayUnits = "MB" };
_exceptionCounter ??= new IncrementingPollingCounter("exception-count", this, () => Exception.GetExceptionCount()) { DisplayName = "Exception Count", DisplayRateTimeScale = new TimeSpan(0, 0, 1) };
_gcTimeCounter ??= new PollingCounter("time-in-gc", this, () => GC.GetLastGCPercentTimeInGC()) { DisplayName = "% Time in GC since last GC", DisplayUnits = "%" };
_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" };
-#endif // !NATIVEAOT
_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" };
<JitOptimizationSensitive>true</JitOptimizationSensitive>
<!-- This test has a secondary thread with an infinite loop -->
<UnloadabilityIncompatible>true</UnloadabilityIncompatible>
+ <EventSourceSupport Condition="'$(TestBuildMode)' == 'nativeaot'">true</EventSourceSupport>
</PropertyGroup>
<ItemGroup>
<Compile Include="runtimecounters.cs" />
<ProjectReference Include="../common/common.csproj" />
</ItemGroup>
+
+ <!-- Hack to get NativeAOT assemblies into IlcReference
+ In CoreCLR tests, these assemblies get copied to CORE_ROOT, which NativeAOT doesn't use
+ -->
+ <Import Project="$(RepoRoot)eng/liveBuilds.targets" Condition="'$(TestBuildMode)' == 'nativeaot'" />
+ <!-- Get all the *.dll files that has IsNative != "true"-->
+ <Target Name="GetRequiredNativeAOTAssemblies"
+ DependsOnTargets="ResolveLibrariesRuntimeFilesFromLocalBuild"
+ BeforeTargets="ComputeIlcCompileInputs"
+ Condition="'$(TestBuildMode)' == 'nativeaot'">
+ <ItemGroup>
+ <IlcReference Include="@(LibrariesRuntimeFiles)" Condition="'%(Extension)' == '.dll' and '%(LibrariesRuntimeFiles.IsNative)' != 'true'"/>
+ </ItemGroup>
+ </Target>
</Project>