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

Implemented C# GC get heap size/ get used size #208

Merged
merged 8 commits into from
Jul 26, 2023
11 changes: 6 additions & 5 deletions src/coreclr/vm/mono/mono_coreclr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ struct HostStruct
gboolean (*class_is_valuetype)(MonoClass* klass);
MonoException* (*exception_from_name_msg)(MonoImage* image, const char* name_space, const char* name, const char* msg);
MonoReflectionField* (*field_get_object)(MonoDomain* domain, MonoClass* klass, MonoClassField* field);
gint64 (*gc_get_heap_size)();
gint64 (*gc_get_used_size)();
intptr_t (*gchandle_get_target_v2)(intptr_t handleIn);
uintptr_t (*gchandle_new_v2)(MonoObject* obj, gboolean pinned);
uintptr_t (*gchandle_new_weakref_v2)(MonoObject* obj, gboolean track_resurrection);
Expand Down Expand Up @@ -1292,11 +1294,10 @@ extern "C" EXPORT_API int EXPORT_CC mono_gc_collect_a_little ()
return 0;
}

// Generated by UnityEmbedHost.Generator - Commit these changes
extern "C" EXPORT_API gint64 EXPORT_CC mono_gc_get_heap_size()
{
FCALL_CONTRACT;
// NOT CORRECT
return GCHeapUtilities::GetGCHeap()->GetTotalBytesInUse();
return g_HostStruct->gc_get_heap_size();
}

extern "C" EXPORT_API gint64 EXPORT_CC mono_gc_get_max_time_slice_ns ()
Expand All @@ -1305,10 +1306,10 @@ extern "C" EXPORT_API gint64 EXPORT_CC mono_gc_get_max_time_slice_ns ()
return 0;
}

// Generated by UnityEmbedHost.Generator - Commit these changes
extern "C" EXPORT_API gint64 EXPORT_CC mono_gc_get_used_size()
{
FCALL_CONTRACT;
return GCHeapUtilities::GetGCHeap()->GetTotalBytesInUse();
return g_HostStruct->gc_get_used_size();
}

extern "C" EXPORT_API gboolean EXPORT_CC mono_gc_is_incremental ()
Expand Down
45 changes: 45 additions & 0 deletions unity/UnityEmbedHost.Tests/BaseEmbeddingApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,51 @@ public void UnityMethodIsGenericReturnsProperValue(Type objType, string methodNa
Assert.That(isGeneric, Is.EqualTo(expectedResult));
}

[Test]
[Timeout(50000)]
public void GcGetHeapSizeReturnsProperValue()
{
GC.Collect(0,GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();

long heapSize = ClrHost.gc_get_heap_size();
while (heapSize == 0)
{
Thread.Sleep(0);
heapSize = ClrHost.gc_get_used_size();
}
Assert.NotZero(heapSize);
int dataSize = 1024 * 1024 * 100;
int[] data = new int[dataSize];
GC.Collect();
heapSize = ClrHost.gc_get_heap_size();
Assert.Greater(heapSize, dataSize * sizeof(int));
GC.KeepAlive(data);
}

[Test]
[Timeout(50000)]
public void GcGetUsedSizeReturnsProperValue()
{
GC.Collect(0,GCCollectionMode.Forced, true);
GC.WaitForPendingFinalizers();

long usedSize = ClrHost.gc_get_used_size();
while (usedSize == 0)
{
Thread.Sleep(0);
usedSize = ClrHost.gc_get_used_size();
}

Assert.NotZero(usedSize);
int dataSize = 1024 * 1024 * 100;
int[] data = new int[dataSize];
GC.Collect();
usedSize = ClrHost.gc_get_used_size();
Assert.Greater(usedSize, dataSize * sizeof(int));
GC.KeepAlive(data);
}

static List<object?> FlattenedArray(Array arr)
{
var result = new List<object?>();
Expand Down
17 changes: 16 additions & 1 deletion unity/unity-embed-host/CoreCLRHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,7 @@ public static bool unity_class_is_abstract(
Type t = klass.TypeFromHandleIntPtr();
return t.IsAbstract;
}

private static ConcurrentDictionary<IntPtr, bool> s_isBlittableCache = new ConcurrentDictionary<IntPtr, bool>();
[return: NativeCallbackType("gboolean")]
public static bool class_is_blittable(
Expand Down Expand Up @@ -671,6 +671,21 @@ public static bool unity_mono_method_is_generic(
return metBase.IsGenericMethodDefinition;
}

[return: NativeCallbackType("gint64")]
public static long gc_get_heap_size()
{
var info = GC.GetGCMemoryInfo();
return info.HeapSizeBytes;
}

[return: NativeCallbackType("gint64")]
public static long gc_get_used_size()
{
var info = GC.GetGCMemoryInfo();
var heapSz = info.HeapSizeBytes;
return heapSz - info.FragmentedBytes;
}

static void Log(string message)
{
var bytes = System.Text.Encoding.UTF8.GetBytes(message);
Expand Down