Skip to content

Commit

Permalink
Return HardLimitBytes from GCMemoryInfo.TotalAvailableMemoryBytes (do…
Browse files Browse the repository at this point in the history
…tnet/coreclr#25437)

* 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 dotnet/coreclr#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"


Commit migrated from dotnet/coreclr@11137fb
  • Loading branch information
Andy Hanson authored and jkotas committed Jul 8, 2019
1 parent 4f2bed7 commit 7585868
Show file tree
Hide file tree
Showing 7 changed files with 57 additions and 45 deletions.
39 changes: 21 additions & 18 deletions src/coreclr/src/System.Private.CoreLib/src/System/GC.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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()
Expand Down
24 changes: 13 additions & 11 deletions src/coreclr/src/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
11 changes: 6 additions & 5 deletions src/coreclr/src/gc/gcimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 6 additions & 5 deletions src/coreclr/src/gc/gcinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/src/vm/comutilnative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/src/vm/comutilnative.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ public readonly struct GCMemoryInfo
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; }

Expand Down

0 comments on commit 7585868

Please sign in to comment.