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

[profiler] Rework GC roots reporting. #5710

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEnums.cs
Expand Up @@ -54,6 +54,8 @@ enum LogEventType {
HeapEnd = 1 << 4,
HeapObject = 2 << 4,
HeapRoots = 3 << 4,
HeapRootRegister = 4 << 4,
HeapRootUnregister = 5 << 4,

SampleHit = 0 << 4,
SampleUnmanagedSymbol = 1 << 4,
Expand Down Expand Up @@ -214,4 +216,23 @@ public enum LogHeapshotMode {
Milliseconds = 3,
Collections = 4,
}

// mono/metadata/mono-gc.h : MonoGCRootSource
public enum LogHeapRootSource {
External = 0,
Stack = 1,
FinalizerQueue = 2,
StaticVariable = 3,
ThreadLocalVariable = 4,
ContextLocalVariable = 5,
GCHandle = 6,
JIT = 7,
Threading = 8,
AppDomain = 9,
Reflection = 10,
Marshal = 11,
ThreadPool = 12,
Debugger = 13,
RuntimeHandle = 14,
}
}
Expand Up @@ -94,6 +94,14 @@ public virtual void Visit (HeapRootsEvent ev)
{
}

public virtual void Visit (HeapRootRegisterEvent ev)
{
}

public virtual void Visit (HeapRootUnregisterEvent ev)
{
}

public virtual void Visit (GCEvent ev)
{
}
Expand Down
24 changes: 24 additions & 0 deletions mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogEvents.cs
Expand Up @@ -257,6 +257,8 @@ public struct HeapRoot {
public LogHeapRootAttributes Attributes { get; internal set; }

public long ExtraInfo { get; internal set; }

public long AddressPointer { get; internal set; }
}

public long MaxGenerationCollectionCount { get; internal set; }
Expand All @@ -269,6 +271,28 @@ internal override void Accept (LogEventVisitor visitor)
}
}

public sealed class HeapRootRegisterEvent : LogEvent {
public long Start { get; internal set; }
public long Size { get; internal set; }
public LogHeapRootSource Kind { get; internal set; }
public long Key { get; internal set; }
public string Message { get; internal set; }

internal override void Accept (LogEventVisitor visitor)
{
visitor.Visit (this);
}
}

public sealed class HeapRootUnregisterEvent : LogEvent {
public long Start { get; internal set; }

internal override void Accept (LogEventVisitor visitor)
{
visitor.Visit (this);
}
}

public sealed class GCEvent : LogEvent {

public LogGCEvent Type { get; internal set; }
Expand Down
73 changes: 51 additions & 22 deletions mcs/class/Mono.Profiler.Log/Mono.Profiler.Log/LogProcessor.cs
Expand Up @@ -392,44 +392,73 @@ LogEvent ReadEvent ()
ev = new HeapEndEvent ();
break;
case LogEventType.HeapObject: {
HeapObjectEvent hoe = new HeapObjectEvent {
var refs = Array.Empty <HeapObjectEvent.HeapObjectReference> ();
ev = new HeapObjectEvent {
ObjectPointer = ReadObject (),
ClassPointer = ReadPointer (),
ObjectSize = (long) _reader.ReadULeb128 (),
References = refs = new HeapObjectEvent.HeapObjectReference [(int) _reader.ReadULeb128 ()],
};

var list = new HeapObjectEvent.HeapObjectReference [(int) _reader.ReadULeb128 ()];

for (var i = 0; i < list.Length; i++) {
list [i] = new HeapObjectEvent.HeapObjectReference {
for (var i = 0; i < refs.Length; i++) {
refs [i] = new HeapObjectEvent.HeapObjectReference {
Offset = (long) _reader.ReadULeb128 (),
ObjectPointer = ReadObject (),
};
}

hoe.References = list;
ev = hoe;

break;
}

case LogEventType.HeapRoots: {
// TODO: This entire event makes no sense.
var hre = new HeapRootsEvent ();
var list = new HeapRootsEvent.HeapRoot [(int) _reader.ReadULeb128 ()];

hre.MaxGenerationCollectionCount = (long) _reader.ReadULeb128 ();
var roots = Array.Empty<HeapRootsEvent.HeapRoot> ();
ev = new HeapRootsEvent () {
Roots = roots = new HeapRootsEvent.HeapRoot [(int) _reader.ReadULeb128 ()],
MaxGenerationCollectionCount = StreamHeader.FormatVersion < 15 ? (long) _reader.ReadULeb128 () : -1,
};

for (var i = 0; i < list.Length; i++) {
list [i] = new HeapRootsEvent.HeapRoot {
ObjectPointer = ReadObject (),
Attributes = StreamHeader.FormatVersion == 13 ? (LogHeapRootAttributes) _reader.ReadByte () : (LogHeapRootAttributes) _reader.ReadULeb128 (),
ExtraInfo = (long) _reader.ReadULeb128 (),
};
for (var i = 0; i < roots.Length; i++) {
if (StreamHeader.FormatVersion < 13) {
roots [i] = new HeapRootsEvent.HeapRoot {
ObjectPointer = ReadObject (),
Attributes = (LogHeapRootAttributes) _reader.ReadULeb128 (),
ExtraInfo = (long) _reader.ReadULeb128 (),
AddressPointer = -1,
};
} else if (StreamHeader.FormatVersion < 15) {
roots [i] = new HeapRootsEvent.HeapRoot {
ObjectPointer = ReadObject (),
Attributes = (LogHeapRootAttributes) _reader.ReadByte (),
ExtraInfo = (long) _reader.ReadULeb128 (),
AddressPointer = -1,
};
} else {
roots [i] = new HeapRootsEvent.HeapRoot {
ObjectPointer = ReadObject (),
Attributes = (LogHeapRootAttributes) 0,
ExtraInfo = 0,
AddressPointer = ReadPointer (),
};
}
}

hre.Roots = list;
ev = hre;
break;
}
case LogEventType.HeapRootRegister: {
ev = new HeapRootRegisterEvent () {
Start = ReadPointer (),
Size = (long) _reader.ReadULeb128 (),
Kind = (LogHeapRootSource) _reader.ReadByte (),
Key = ReadPointer (),
Message = _reader.ReadCString ()
};

break;
}
case LogEventType.HeapRootUnregister: {
ev = new HeapRootUnregisterEvent () {
Start = ReadPointer ()
};

break;
}
Expand Down Expand Up @@ -586,7 +615,7 @@ long ReadPointer ()

long ReadObject ()
{
return _reader.ReadSLeb128 () + _bufferHeader.ObjectBase << 3;
return (_reader.ReadSLeb128 () + _bufferHeader.ObjectBase) << 3;
}

long ReadMethod ()
Expand Down
20 changes: 12 additions & 8 deletions mono/metadata/boehm-gc.c
Expand Up @@ -547,21 +547,21 @@ register_root (gpointer arg)
}

int
mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource source, const char *msg)
mono_gc_register_root (char *start, size_t size, void *descr, MonoGCRootSource source, void *key, const char *msg)
{
RootData root_data;
root_data.start = start;
/* Boehm root processing requires one byte past end of region to be scanned */
root_data.end = start + size + 1;
GC_call_with_alloc_lock (register_root, &root_data);

MONO_PROFILER_RAISE (gc_root_register, ((const mono_byte*)start, size, source, key, msg));
return TRUE;
}

int
mono_gc_register_root_wbarrier (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, const char *msg)
mono_gc_register_root_wbarrier (char *start, size_t size, MonoGCDescriptor descr, MonoGCRootSource source, void *key, const char *msg)
{
return mono_gc_register_root (start, size, descr, source, msg);
return mono_gc_register_root (start, size, descr, source, key, msg);
}

static gpointer
Expand All @@ -576,6 +576,7 @@ void
mono_gc_deregister_root (char* addr)
{
GC_call_with_alloc_lock (deregister_root, addr);
MONO_PROFILER_RAISE (gc_root_unregister, ((const mono_byte*)addr));
}

static void
Expand Down Expand Up @@ -671,14 +672,17 @@ mono_gc_make_root_descr_all_refs (int numbits)
}

void*
mono_gc_alloc_fixed (size_t size, void *descr, MonoGCRootSource source, const char *msg)
mono_gc_alloc_fixed (size_t size, void *descr, MonoGCRootSource source, void *key, const char *msg)
{
return GC_MALLOC_UNCOLLECTABLE (size);
void *start = GC_MALLOC_UNCOLLECTABLE (size);
MONO_PROFILER_RAISE (gc_root_register, (start, size, source, key, msg));
return start;
}

void
mono_gc_free_fixed (void* addr)
{
MONO_PROFILER_RAISE (gc_root_unregister, (addr));
GC_FREE (addr);
}

Expand Down Expand Up @@ -1634,7 +1638,7 @@ handle_data_alloc_entries (HandleData *handles)
handles->entries = (void **)g_malloc0 (sizeof (*handles->entries) * handles->size);
handles->domain_ids = (guint16 *)g_malloc0 (sizeof (*handles->domain_ids) * handles->size);
} else {
handles->entries = (void **)mono_gc_alloc_fixed (sizeof (*handles->entries) * handles->size, NULL, MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
handles->entries = (void **)mono_gc_alloc_fixed (sizeof (*handles->entries) * handles->size, NULL, MONO_ROOT_SOURCE_GC_HANDLE, NULL, "gc handles table");
}
handles->bitmap = (guint32 *)g_malloc0 (handles->size / CHAR_BIT);
}
Expand Down Expand Up @@ -1701,7 +1705,7 @@ handle_data_grow (HandleData *handles, gboolean track)
handles->domain_ids = domain_ids;
} else {
gpointer *entries;
entries = (void **)mono_gc_alloc_fixed (sizeof (*handles->entries) * new_size, NULL, MONO_ROOT_SOURCE_GC_HANDLE, "gc handles table");
entries = (void **)mono_gc_alloc_fixed (sizeof (*handles->entries) * new_size, NULL, MONO_ROOT_SOURCE_GC_HANDLE, NULL, "gc handles table");
mono_gc_memmove_aligned (entries, handles->entries, sizeof (*handles->entries) * handles->size);
mono_gc_free_fixed (handles->entries);
handles->entries = entries;
Expand Down
2 changes: 1 addition & 1 deletion mono/metadata/custom-attrs.c
Expand Up @@ -761,7 +761,7 @@ create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, gu
memset (params, 0, sizeof (void*) * sig->param_count);
} else {
/* Allocate using GC so it gets GC tracking */
params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, "custom attribute parameters");
params = (void **)mono_gc_alloc_fixed (sig->param_count * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_REFLECTION, NULL, "custom attribute parameters");
}

/* skip prolog */
Expand Down
34 changes: 26 additions & 8 deletions mono/metadata/domain.c
Expand Up @@ -292,6 +292,24 @@ mono_ptrarray_hash (gpointer *s)
return hash;
}

//g_malloc on sgen and mono_gc_alloc_fixed on boehm
static void*
gc_alloc_fixed_non_heap (size_t size)
{
if (mono_gc_is_moving ())
return g_malloc0 (size);
else
return mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, NULL, "Misc AppDomain Memory");
}

static void
gc_free_fixed_no_heap (void *ptr)
{
if (mono_gc_is_moving ())
return g_free (ptr);
else
return mono_gc_free_fixed (ptr);
}
/*
* Allocate an id for domain and set domain->domain_id.
* LOCKING: must be called while holding appdomains_mutex.
Expand All @@ -306,7 +324,8 @@ domain_id_alloc (MonoDomain *domain)
int id = -1, i;
if (!appdomains_list) {
appdomain_list_size = 2;
appdomains_list = (MonoDomain **)mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "domains list");
appdomains_list = (MonoDomain **)gc_alloc_fixed_non_heap (appdomain_list_size * sizeof (void*));

}
for (i = appdomain_next; i < appdomain_list_size; ++i) {
if (!appdomains_list [i]) {
Expand All @@ -328,9 +347,9 @@ domain_id_alloc (MonoDomain *domain)
if (new_size >= (1 << 16))
g_assert_not_reached ();
id = appdomain_list_size;
new_list = (MonoDomain **)mono_gc_alloc_fixed (new_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "domains list");
new_list = (MonoDomain **)gc_alloc_fixed_non_heap (new_size * sizeof (void*));
memcpy (new_list, appdomains_list, appdomain_list_size * sizeof (void*));
mono_gc_free_fixed (appdomains_list);
gc_free_fixed_no_heap (appdomains_list);
appdomains_list = new_list;
appdomain_list_size = new_size;
}
Expand Down Expand Up @@ -387,10 +406,9 @@ mono_domain_create (void)
mono_appdomains_unlock ();

if (!mono_gc_is_moving ()) {
domain = (MonoDomain *)mono_gc_alloc_fixed (sizeof (MonoDomain), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "domain object");
domain = (MonoDomain *)mono_gc_alloc_fixed (sizeof (MonoDomain), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, NULL, "domain object");
} else {
domain = (MonoDomain *)mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc, MONO_ROOT_SOURCE_DOMAIN, "domain object");
mono_gc_register_root ((char*)&(domain->MONO_DOMAIN_FIRST_GC_TRACKED), G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_LAST_GC_TRACKED) - G_STRUCT_OFFSET (MonoDomain, MONO_DOMAIN_FIRST_GC_TRACKED), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "misc domain fields");
domain = (MonoDomain *)mono_gc_alloc_fixed (sizeof (MonoDomain), domain_gc_desc, MONO_ROOT_SOURCE_DOMAIN, NULL, "domain object");
}
domain->shadow_serial = shadow_serial;
domain->domain = NULL;
Expand Down Expand Up @@ -952,7 +970,7 @@ mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
*/
mono_appdomains_lock ();
size = appdomain_list_size;
copy = (MonoDomain **)mono_gc_alloc_fixed (appdomain_list_size * sizeof (void*), MONO_GC_DESCRIPTOR_NULL, MONO_ROOT_SOURCE_DOMAIN, "temporary domains list");
copy = (MonoDomain **)gc_alloc_fixed_non_heap (appdomain_list_size * sizeof (void*));
memcpy (copy, appdomains_list, appdomain_list_size * sizeof (void*));
mono_appdomains_unlock ();

Expand All @@ -961,7 +979,7 @@ mono_domain_foreach (MonoDomainFunc func, gpointer user_data)
func (copy [i], user_data);
}

mono_gc_free_fixed (copy);
gc_free_fixed_no_heap (copy);
}

/* FIXME: maybe we should integrate this with mono_assembly_open? */
Expand Down