diff --git a/src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs b/src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs index 72c2aca14da2..850f1256eb12 100644 --- a/src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs +++ b/src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs @@ -17,7 +17,12 @@ public readonly struct GCMemoryInfo public long MemoryLoadBytes { get; } /// - /// Total available memory for the GC to use when the last GC ocurred. By default this is the physical memory on the machine, but it may be customized by specifying a HardLimit. + /// Total available memory for the GC to use when the last GC ocurred. + /// + /// If the environment variable COMPlus_GCHeapHardLimit is set, + /// or "Server.GC.HeapHardLimit" is in runtimeconfig.json, this will come from that. + /// If the program is run in a container, this will be an implementation-defined fraction of the container's size. + /// Else, this is the physical memory on the machine that was available for the GC to use when the last GC occurred. /// public long TotalAvailableMemoryBytes { get; } diff --git a/src/System.Private.CoreLib/src/System/GC.cs b/src/System.Private.CoreLib/src/System/GC.cs index 89c277e544e5..e67c043e627b 100644 --- a/src/System.Private.CoreLib/src/System/GC.cs +++ b/src/System.Private.CoreLib/src/System/GC.cs @@ -54,26 +54,28 @@ public enum GCNotificationStatus public static class GC { [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern void GetMemoryInfo(out uint highMemLoadThreshold, - out ulong totalPhysicalMem, - out uint lastRecordedMemLoad, + internal static extern void GetMemoryInfo(out ulong highMemLoadThresholdBytes, + out ulong totalAvailableMemoryBytes, + out ulong lastRecordedMemLoadBytes, + out uint lastRecordedMemLoadPct, // The next two are size_t - out UIntPtr lastRecordedHeapSize, - out UIntPtr lastRecordedFragmentation); + out UIntPtr lastRecordedHeapSizeBytes, + out UIntPtr lastRecordedFragmentationBytes); public static GCMemoryInfo GetGCMemoryInfo() { - GetMemoryInfo(out uint highMemLoadThreshold, - out ulong totalPhysicalMem, - out uint lastRecordedMemLoad, - out UIntPtr lastRecordedHeapSize, - out UIntPtr lastRecordedFragmentation); + GetMemoryInfo(out ulong highMemLoadThresholdBytes, + out ulong totalAvailableMemoryBytes, + out ulong lastRecordedMemLoadBytes, + out uint _, + out UIntPtr lastRecordedHeapSizeBytes, + out UIntPtr lastRecordedFragmentationBytes); - return new GCMemoryInfo((long)((double)highMemLoadThreshold / 100 * totalPhysicalMem), - (long)((double)lastRecordedMemLoad / 100 * totalPhysicalMem), - (long)totalPhysicalMem, - (long)(ulong)lastRecordedHeapSize, - (long)(ulong)lastRecordedFragmentation); + return new GCMemoryInfo(highMemoryLoadThresholdBytes: (long)highMemLoadThresholdBytes, + memoryLoadBytes: (long)lastRecordedMemLoadBytes, + totalAvailableMemoryBytes: (long)totalAvailableMemoryBytes, + heapSizeBytes: (long)(ulong)lastRecordedHeapSizeBytes, + fragmentedBytes: (long)(ulong)lastRecordedFragmentationBytes); } [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] @@ -541,13 +543,14 @@ public MemoryLoadChangeNotification(float lowMemoryPercent, float highMemoryPerc private static float GetMemoryLoad() { - GetMemoryInfo(out uint _, + GetMemoryInfo(out ulong _, out ulong _, - out uint lastRecordedMemLoad, + out ulong _, + out uint lastRecordedMemLoadPct, out UIntPtr _, out UIntPtr _); - return (float)lastRecordedMemLoad / 100; + return (float)lastRecordedMemLoadPct; } private static bool InvokeMemoryLoadChangeNotifications() diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp index f4d877fe887d..f107b134ca23 100644 --- a/src/gc/gc.cpp +++ b/src/gc/gc.cpp @@ -36814,17 +36814,19 @@ unsigned int GCHeap::GetCondemnedGeneration() return gc_heap::settings.condemned_generation; } -void GCHeap::GetMemoryInfo(uint32_t* highMemLoadThreshold, - uint64_t* totalPhysicalMem, - uint32_t* lastRecordedMemLoad, - size_t* lastRecordedHeapSize, - size_t* lastRecordedFragmentation) -{ - *highMemLoadThreshold = gc_heap::high_memory_load_th; - *totalPhysicalMem = gc_heap::total_physical_mem; - *lastRecordedMemLoad = gc_heap::last_gc_memory_load; - *lastRecordedHeapSize = gc_heap::last_gc_heap_size; - *lastRecordedFragmentation = gc_heap::last_gc_fragmentation; +void GCHeap::GetMemoryInfo(uint64_t* highMemLoadThresholdBytes, + uint64_t* totalAvailableMemoryBytes, + uint64_t* lastRecordedMemLoadBytes, + uint32_t* lastRecordedMemLoadPct, + size_t* lastRecordedHeapSizeBytes, + size_t* lastRecordedFragmentationBytes) +{ + *highMemLoadThresholdBytes = (uint64_t) (((double)gc_heap::high_memory_load_th) / 100 * gc_heap::total_physical_mem); + *totalAvailableMemoryBytes = gc_heap::heap_hard_limit != 0 ? gc_heap::heap_hard_limit : gc_heap::total_physical_mem; + *lastRecordedMemLoadBytes = (uint64_t) (((double)gc_heap::last_gc_memory_load) / 100 * gc_heap::total_physical_mem); + *lastRecordedMemLoadPct = gc_heap::last_gc_memory_load; + *lastRecordedHeapSizeBytes = gc_heap::last_gc_heap_size; + *lastRecordedFragmentationBytes = gc_heap::last_gc_fragmentation; } int GCHeap::GetGcLatencyMode() diff --git a/src/gc/gcimpl.h b/src/gc/gcimpl.h index b1d4e07981d5..965bfa698770 100644 --- a/src/gc/gcimpl.h +++ b/src/gc/gcimpl.h @@ -171,11 +171,12 @@ class GCHeap : public IGCHeapInternal unsigned GetCondemnedGeneration(); - void GetMemoryInfo(uint32_t* highMemLoadThreshold, - uint64_t* totalPhysicalMem, - uint32_t* lastRecordedMemLoad, - size_t* lastRecordedHeapSize, - size_t* lastRecordedFragmentation); + void GetMemoryInfo(uint64_t* highMemLoadThresholdBytes, + uint64_t* totalAvailableMemoryBytes, + uint64_t* lastRecordedMemLoadBytes, + uint32_t* lastRecordedMemLoadPct, + size_t* lastRecordedHeapSizeBytes, + size_t* lastRecordedFragmentationBytes); int GetGcLatencyMode(); int SetGcLatencyMode(int newLatencyMode); diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h index 6d09a62824e5..062743ff37b2 100644 --- a/src/gc/gcinterface.h +++ b/src/gc/gcinterface.h @@ -605,11 +605,12 @@ class IGCHeap { // lastRecordedMemLoad - physical memory load in percentage recorded in the last GC // lastRecordedHeapSize - total managed heap size recorded in the last GC // lastRecordedFragmentation - total fragmentation in the managed heap recorded in the last GC - virtual void GetMemoryInfo(uint32_t* highMemLoadThreshold, - uint64_t* totalPhysicalMem, - uint32_t* lastRecordedMemLoad, - size_t* lastRecordedHeapSize, - size_t* lastRecordedFragmentation) = 0; + virtual void GetMemoryInfo(uint64_t* highMemLoadThresholdBytes, + uint64_t* totalPhysicalMemoryBytes, + uint64_t* lastRecordedMemLoadBytes, + uint32_t* lastRecordedMemLoadPct, + size_t* lastRecordedHeapSizeBytes, + size_t* lastRecordedFragmentationBytes) = 0; // Gets the current GC latency mode. virtual int GetGcLatencyMode() = 0; diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index 930905b7804f..bdb23923d668 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -877,15 +877,15 @@ UINT64 GCInterface::m_remPressure[NEW_PRESSURE_COUNT] = {0, 0, 0, 0}; // his // (m_iteration % NEW_PRESSURE_COUNT) is used as an index into m_addPressure and m_remPressure UINT GCInterface::m_iteration = 0; -FCIMPL5(void, GCInterface::GetMemoryInfo, UINT32* highMemLoadThreshold, UINT64* totalPhysicalMem, UINT32* lastRecordedMemLoad, size_t* lastRecordedHeapSize, size_t* lastRecordedFragmentation) +FCIMPL6(void, GCInterface::GetMemoryInfo, UINT64* highMemLoadThreshold, UINT64* totalAvailableMemoryBytes, UINT64* lastRecordedMemLoadBytes, UINT32* lastRecordedMemLoadPct, size_t* lastRecordedHeapSizeBytes, size_t* lastRecordedFragmentationBytes) { FCALL_CONTRACT; FC_GC_POLL_NOT_NEEDED(); - return GCHeapUtilities::GetGCHeap()->GetMemoryInfo(highMemLoadThreshold, totalPhysicalMem, - lastRecordedMemLoad, - lastRecordedHeapSize, lastRecordedFragmentation); + return GCHeapUtilities::GetGCHeap()->GetMemoryInfo(highMemLoadThreshold, totalAvailableMemoryBytes, + lastRecordedMemLoadBytes, lastRecordedMemLoadPct, + lastRecordedHeapSizeBytes, lastRecordedFragmentationBytes); } FCIMPLEND diff --git a/src/vm/comutilnative.h b/src/vm/comutilnative.h index 6afbc5a45e3d..5267d6ef732b 100644 --- a/src/vm/comutilnative.h +++ b/src/vm/comutilnative.h @@ -110,7 +110,7 @@ class GCInterface { static FORCEINLINE UINT64 InterlockedAdd(UINT64 *pAugend, UINT64 addend); static FORCEINLINE UINT64 InterlockedSub(UINT64 *pMinuend, UINT64 subtrahend); - static FCDECL5(void, GetMemoryInfo, UINT32* highMemLoadThreshold, UINT64* totalPhysicalMem, UINT32* lastRecordedMemLoad, size_t* lastRecordedHeapSize, size_t* lastRecordedFragmentation); + static FCDECL6(void, GetMemoryInfo, UINT64* highMemLoadThresholdBytes, UINT64* totalAvailableMemoryBytes, UINT64* lastRecordedMemLoadBytes, UINT32* lastRecordedMemLoadPct, size_t* lastRecordedHeapSizBytes, size_t* lastRecordedFragmentationBytes); static FCDECL0(int, GetGcLatencyMode); static FCDECL1(int, SetGcLatencyMode, int newLatencyMode); static FCDECL0(int, GetLOHCompactionMode);