Skip to content

Commit

Permalink
Add Mono System.Diagnostics.Tracing.RuntimeEventSource. (#51734)
Browse files Browse the repository at this point in the history
Mono didn't register RuntimeEventSource on startup and was missing a number of runtime specific counters. This commit implements support for all current counters in RuntimeEventSource on Mono runtime.
  • Loading branch information
lateralusX authored Apr 26, 2021
1 parent 207b03a commit 3782e6e
Show file tree
Hide file tree
Showing 32 changed files with 454 additions and 58 deletions.
8 changes: 8 additions & 0 deletions src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,14 @@ ep_rt_init (void)
}
}

static
inline
void
ep_rt_init_finish (void)
{
STATIC_CONTRACT_NOTHROW;
}

static
inline
void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,10 @@
<method name="GetActiveTaskFromId" />
</type>
</assembly>

<assembly fullname="System.Private.CoreLib" feature="System.Diagnostics.Tracing.EventSource.IsSupported" featurevalue="true" featuredefault="true">
<type fullname="System.Diagnostics.Tracing.RuntimeEventSource">
<method signature="System.Void Initialize()" />
</type>
</assembly>
</linker>
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ internal sealed partial class RuntimeEventSource : EventSource
private PollingCounter? _timerCounter;
private PollingCounter? _fragmentationCounter;
private PollingCounter? _committedCounter;

#if !MONO
private IncrementingPollingCounter? _exceptionCounter;
private PollingCounter? _gcTimeCounter;
private PollingCounter? _gen0SizeCounter;
Expand All @@ -41,7 +39,6 @@ internal sealed partial class RuntimeEventSource : EventSource
private PollingCounter? _assemblyCounter;
private PollingCounter? _ilBytesJittedCounter;
private PollingCounter? _methodsJittedCounter;
#endif

public static void Initialize()
{
Expand Down Expand Up @@ -78,7 +75,6 @@ protected override void OnEventCommand(EventCommandEventArgs command)
return gcInfo.HeapSizeBytes != 0 ? gcInfo.FragmentedBytes * 100d / gcInfo.HeapSizeBytes : 0;
}) { DisplayName = "GC Fragmentation", DisplayUnits = "%" };
_committedCounter ??= new PollingCounter("gc-committed", this, () => (double)(GC.GetGCMemoryInfo().TotalCommittedBytes / 1_000_000)) { DisplayName = "GC Committed Bytes", DisplayUnits = "MB" };
#if !MONO
_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 = "%" };
_gen0SizeCounter ??= new PollingCounter("gen-0-size", this, () => GC.GetGenerationSize(0)) { DisplayName = "Gen 0 Size", DisplayUnits = "B" };
Expand All @@ -89,7 +85,6 @@ protected override void OnEventCommand(EventCommandEventArgs command)
_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" };
#endif
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

using System.Runtime.CompilerServices;

#if FEATURE_PERFTRACING

namespace System.Diagnostics.Tracing
{

internal static partial class EventPipeInternal
{
#if FEATURE_PERFTRACING
// These ICalls are used by the configuration APIs to interact with EventPipe.
//
[MethodImplAttribute(MethodImplOptions.InternalCall)]
Expand Down Expand Up @@ -58,7 +58,35 @@ internal static unsafe IntPtr GetProvider(string providerName)

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern unsafe IntPtr GetWaitHandle(ulong sessionID);
}
}

#endif // FEATURE_PERFTRACING

//
// This ICall are used as part of getting runtime implemented counter values.
//

//
// NOTE, keep in sync with icall-eventpipe.c, EventPipeRuntimeCounters.
//
internal enum RuntimeCounters
{
ASSEMBLY_COUNT,
EXCEPTION_COUNT,
GC_NURSERY_SIZE_BYTES,
GC_MAJOR_SIZE_BYTES,
GC_LARGE_OBJECT_SIZE_BYTES,
GC_LAST_PERCENT_TIME_IN_GC,
JIT_IL_BYTES_JITTED,
JIT_METHODS_JITTED
}

#if FEATURE_PERFTRACING
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern ulong GetRuntimeCounterValue(RuntimeCounters counterID);
#else
internal static ulong GetRuntimeCounterValue(RuntimeCounters counterID)
{
return 0;
}
#endif
}
}
6 changes: 6 additions & 0 deletions src/mono/System.Private.CoreLib/src/System/Exception.Mono.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics.Tracing;

namespace System
{
[StructLayout(LayoutKind.Sequential)]
public partial class Exception
{
internal static uint GetExceptionCount()
{
return (uint)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.EXCEPTION_COUNT);
}

internal readonly struct DispatchState
{
public readonly MonoStackFrame[]? StackFrames;
Expand Down
26 changes: 26 additions & 0 deletions src/mono/System.Private.CoreLib/src/System/GC.Mono.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Runtime.CompilerServices;
using Internal.Runtime.CompilerServices;
using System.Diagnostics.Tracing;

namespace System
{
Expand Down Expand Up @@ -242,6 +243,7 @@ internal static ulong GetSegmentSize()
private static extern void _GetGCMemoryInfo(out long highMemoryLoadThresholdBytes,
out long memoryLoadBytes,
out long totalAvailableMemoryBytes,
out long totalCommittedBytes,
out long heapSizeBytes,
out long fragmentedBytes);

Expand All @@ -252,6 +254,7 @@ public static GCMemoryInfo GetGCMemoryInfo()
_GetGCMemoryInfo(out data._highMemoryLoadThresholdBytes,
out data._memoryLoadBytes,
out data._totalAvailableMemoryBytes,
out data._totalCommittedBytes,
out data._heapSizeBytes,
out data._fragmentedBytes);

Expand Down Expand Up @@ -286,5 +289,28 @@ public static T[] AllocateArray<T>(int length, bool pinned = false)

return new T[length];
}

internal static ulong GetGenerationSize(int generation)
{
switch (generation) {
case 0 :
return EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.GC_NURSERY_SIZE_BYTES);
case 1 :
case 2 :
return EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.GC_MAJOR_SIZE_BYTES);
case 3 :
return EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.GC_LARGE_OBJECT_SIZE_BYTES);
case 4:
// Pinned object heap.
return 0;
default:
return 0;
}
}

internal static int GetLastGCPercentTimeInGC()
{
return (int)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.GC_LAST_PERCENT_TIME_IN_GC);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Runtime.InteropServices;
using System.Runtime.Loader;
using System.Threading;
using System.Diagnostics.Tracing;

namespace System.Reflection
{
Expand Down Expand Up @@ -87,6 +88,11 @@ internal static Assembly Load(AssemblyName assemblyRef, ref StackCrawlMark stack
return assembly;
}

internal static uint GetAssemblyCount()
{
return (uint)EventPipeInternal.GetRuntimeCounterValue(EventPipeInternal.RuntimeCounters.ASSEMBLY_COUNT);
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern Assembly InternalLoad(string assemblyName, ref StackCrawlMark stackMark, IntPtr ptrLoadContextBinder);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.Serialization;
using Internal.Runtime.CompilerServices;
using System.Diagnostics.Tracing;

namespace System.Runtime.CompilerServices
{
Expand Down Expand Up @@ -153,6 +154,16 @@ 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
23 changes: 23 additions & 0 deletions src/mono/mono/eventpipe/ep-rt-mono.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,9 @@ profiler_eventpipe_thread_exited (
void
ep_rt_mono_init (void);

void
ep_rt_mono_init_finish (void);

void
ep_rt_mono_fini (void);

Expand Down Expand Up @@ -1640,6 +1643,26 @@ ep_rt_mono_init (void)
mono_profiler_set_thread_stopped_callback (profiler, profiler_eventpipe_thread_exited);
}

void
ep_rt_mono_init_finish (void)
{
if (mono_runtime_get_no_exec ())
return;

// Managed init of diagnostics classes, like registration of RuntimeEventSource (if available).
ERROR_DECL (error);

MonoClass *runtime_event_source = mono_class_from_name_checked (mono_defaults.corlib, "System.Diagnostics.Tracing", "RuntimeEventSource", error);
if (is_ok (error) && runtime_event_source) {
MonoMethod *init = mono_class_get_method_from_name_checked (runtime_event_source, "Initialize", -1, 0, error);
if (is_ok (error) && init) {
mono_runtime_try_invoke_handle (init, NULL_HANDLE, NULL, error);
}
}

mono_error_cleanup (error);
}

void
ep_rt_mono_fini (void)
{
Expand Down
9 changes: 9 additions & 0 deletions src/mono/mono/eventpipe/ep-rt-mono.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,15 @@ ep_rt_init (void)
ep_rt_spin_lock_alloc (ep_rt_mono_config_lock_get ());
}

static
inline
void
ep_rt_init_finish (void)
{
extern void ep_rt_mono_init_finish (void);
ep_rt_mono_init_finish ();
}

static
inline
void
Expand Down
2 changes: 2 additions & 0 deletions src/mono/mono/metadata/assembly-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,5 +150,7 @@ mono_set_assemblies_path_direct (char **path);
gboolean
mono_assembly_is_jit_optimizer_disabled (MonoAssembly *assembly);

guint32
mono_assembly_get_count (void);

#endif /* __MONO_METADATA_ASSEMBLY_INTERNALS_H__ */
9 changes: 9 additions & 0 deletions src/mono/mono/metadata/assembly.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ static char **assemblies_path = NULL;

/* keeps track of loaded assemblies, excluding dynamic ones */
static GList *loaded_assemblies = NULL;
static guint32 loaded_assembly_count = 0;
static MonoAssembly *corlib;

static char* unquote (const char *str);
Expand Down Expand Up @@ -2387,6 +2388,7 @@ mono_assembly_request_load_from (MonoImage *image, const char *fname,
image->assembly = ass;

loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
loaded_assembly_count++;
mono_assemblies_unlock ();

#ifdef HOST_WIN32
Expand Down Expand Up @@ -3285,6 +3287,7 @@ mono_assembly_close_except_image_pools (MonoAssembly *assembly)

mono_assemblies_lock ();
loaded_assemblies = g_list_remove (loaded_assemblies, assembly);
loaded_assembly_count--;
mono_assemblies_unlock ();

assembly->image->assembly = NULL;
Expand Down Expand Up @@ -3723,3 +3726,9 @@ mono_assembly_is_jit_optimizer_disabled (MonoAssembly *ass)
return disable_opts;

}

guint32
mono_assembly_get_count (void)
{
return loaded_assembly_count;
}
29 changes: 24 additions & 5 deletions src/mono/mono/metadata/boehm-gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,12 @@ mono_gc_collection_count (int generation)
return GC_get_gc_no ();
}

int64_t
mono_gc_get_generation_size (int generation)
{
return 0;
}

void
mono_stop_world (MonoThreadInfoFlags flags)
{
Expand Down Expand Up @@ -1637,19 +1643,32 @@ mono_gc_ephemeron_array_add (MonoObject *obj)
}

void
mono_gc_get_gcmemoryinfo (gint64* high_memory_load_threshold_bytes,
gint64* memory_load_bytes,
gint64* total_available_memory_bytes,
gint64* heap_size_bytes,
gint64* fragmented_bytes)
mono_gc_get_gcmemoryinfo (
gint64 *high_memory_load_threshold_bytes,
gint64 *memory_load_bytes,
gint64 *total_available_memory_bytes,
gint64 *total_committed_bytes,
gint64 *heap_size_bytes,
gint64 *fragmented_bytes)
{
*high_memory_load_threshold_bytes = 0;
*memory_load_bytes = 0;
*total_available_memory_bytes = 0;
*total_committed_bytes = 0;
*heap_size_bytes = 0;
*fragmented_bytes = 0;
}

void mono_gc_get_gctimeinfo (
guint64 *time_last_gc_100ns,
guint64 *time_since_last_gc_100ns,
guint64 *time_max_gc_100ns)
{
*time_last_gc_100ns = 0;
*time_since_last_gc_100ns = 0;
*time_max_gc_100ns = 0;
}

#else

MONO_EMPTY_SOURCE_FILE (boehm_gc);
Expand Down
4 changes: 2 additions & 2 deletions src/mono/mono/metadata/class-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -1288,7 +1288,7 @@ mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error);
MonoClass *
mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error);

MonoClass *
MONO_COMPONENT_API MonoClass *
mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error);

MonoClass *
Expand Down Expand Up @@ -1430,7 +1430,7 @@ mono_class_set_dim_conflicts (MonoClass *klass, GSList *conflicts);
GSList*
mono_class_get_dim_conflicts (MonoClass *klass);

MonoMethod *
MONO_COMPONENT_API MonoMethod *
mono_class_get_method_from_name_checked (MonoClass *klass, const char *name, int param_count, int flags, MonoError *error);

gboolean
Expand Down
Loading

0 comments on commit 3782e6e

Please sign in to comment.