Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Add property HardLimitBytes to GCMemoryInfo #25437

Merged
merged 7 commits into from Jul 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/System.Private.CoreLib/shared/System/GCMemoryInfo.cs
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
39 changes: 21 additions & 18 deletions 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/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;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it fine to potentially return heap_hard_limit here, which could be larger than total_physical_mem if inproperly configured?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you misconfigure the hard limit, the GC itself won't work quite right either. You get what you asked for. We are not trying to guess whether you meant it or not.

*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/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/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/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/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