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; }
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)]
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()
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()
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);
// 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;
// (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
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);