diff --git a/src/coreclr/vm/mono/mono_coreclr.cpp b/src/coreclr/vm/mono/mono_coreclr.cpp index bab6991fa0df3..de3c7b1ef27cb 100644 --- a/src/coreclr/vm/mono/mono_coreclr.cpp +++ b/src/coreclr/vm/mono/mono_coreclr.cpp @@ -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); @@ -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 () @@ -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 () diff --git a/unity/UnityEmbedHost.Tests/BaseEmbeddingApiTests.cs b/unity/UnityEmbedHost.Tests/BaseEmbeddingApiTests.cs index 9b5ce73f6b877..c1146359856f3 100644 --- a/unity/UnityEmbedHost.Tests/BaseEmbeddingApiTests.cs +++ b/unity/UnityEmbedHost.Tests/BaseEmbeddingApiTests.cs @@ -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 FlattenedArray(Array arr) { var result = new List(); diff --git a/unity/unity-embed-host/CoreCLRHost.cs b/unity/unity-embed-host/CoreCLRHost.cs index d5b0e470f80dc..c1075f262de64 100644 --- a/unity/unity-embed-host/CoreCLRHost.cs +++ b/unity/unity-embed-host/CoreCLRHost.cs @@ -616,7 +616,7 @@ public static bool unity_class_is_abstract( Type t = klass.TypeFromHandleIntPtr(); return t.IsAbstract; } - + private static ConcurrentDictionary s_isBlittableCache = new ConcurrentDictionary(); [return: NativeCallbackType("gboolean")] public static bool class_is_blittable( @@ -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);