Return HardLimitBytes from GCMemoryInfo.TotalAvailableMemoryBytes (#25437)
authorAndy Hanson <anhans@microsoft.com>
Mon, 8 Jul 2019 23:12:06 +0000 (16:12 -0700)
committerJan Kotas <jkotas@microsoft.com>
Mon, 8 Jul 2019 23:12:06 +0000 (16:12 -0700)
* Add property HardLimitBytes to GCMemoryInfo

This adds a new property HardLimitBytes.

Unlike TotalAvailableMemoryBytes,
this will reflect an explicitly set COMPLUS_GCHeapHardLimit.

It will also reflect the fraction of a container's size that we use,
where TotalAvailableMemoryBytes is the total container size.

Normally, though, it is equal to TotalAvailableMemoryBytes.

Fix #38821

* Remove HardLimitBytes; have TotalAvailableMemoryBytes take on its behavior

* Fix typos

* Separate total_physical_mem and heap_hard_limit
so we can compute highMemoryLoadThresholdBytes and memoryLoadBytes

* Do more work in gc.cpp instead of Gc.cs

* Consistently end names in "Bytes"

src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs
src/System.Private.CoreLib/src/System/GC.cs
src/gc/gc.cpp
src/gc/gcimpl.h
src/gc/gcinterface.h
src/vm/comutilnative.cpp
src/vm/comutilnative.h

index 72c2aca..850f125 100644 (file)
@@ -17,7 +17,12 @@ namespace System
         public long MemoryLoadBytes { get; }
 
         /// <summary>
-        /// 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.
         /// </summary>
         public long TotalAvailableMemoryBytes { get; }
 
index 89c277e..e67c043 100644 (file)
@@ -54,26 +54,28 @@ namespace System
     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 @@ namespace System
 
         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()
index f4d877f..f107b13 100644 (file)
@@ -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()
index b1d4e07..965bfa6 100644 (file)
@@ -171,11 +171,12 @@ public:
 
     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);
index 6d09a62..062743f 100644 (file)
@@ -605,11 +605,12 @@ public:
     // 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;
index 930905b..bdb2392 100644 (file)
@@ -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
 
index 6afbc5a..5267d6e 100644 (file)
@@ -110,7 +110,7 @@ public:
     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);