summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaoni Stephens <Maoni0@users.noreply.github.com>2018-04-02 11:10:48 -0700
committerGitHub <noreply@github.com>2018-04-02 11:10:48 -0700
commit2583ce936776a0eac31df904e41d5119840c203b (patch)
tree987571beacb459f7e7fa9ad79cb0d0c013068cc1 /src
parent73fe1a9b6dd1983e35093139bf50ede2b78bbf14 (diff)
downloadcoreclr-2583ce936776a0eac31df904e41d5119840c203b.tar.gz
coreclr-2583ce936776a0eac31df904e41d5119840c203b.tar.bz2
coreclr-2583ce936776a0eac31df904e41d5119840c203b.zip
Added a new API to provide memory information that GC records. This (#17326)
is to be used by BCL for deciding when to trim memory usage in pooling code
Diffstat (limited to 'src')
-rw-r--r--src/gc/gc.cpp66
-rw-r--r--src/gc/gcimpl.h6
-rw-r--r--src/gc/gcinterface.h14
-rw-r--r--src/gc/gcpriv.h13
-rw-r--r--src/mscorlib/src/System/GC.cs8
-rw-r--r--src/vm/comutilnative.cpp12
-rw-r--r--src/vm/comutilnative.h1
-rw-r--r--src/vm/ecalllist.h1
8 files changed, 114 insertions, 7 deletions
diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp
index a23edb9dff..ef9058e6ab 100644
--- a/src/gc/gc.cpp
+++ b/src/gc/gc.cpp
@@ -2467,13 +2467,19 @@ double gc_heap::short_plugs_pad_ratio = 0;
size_t gc_heap::youngest_gen_desired_th;
#endif //BIT64
-uint64_t gc_heap::mem_one_percent;
+uint32_t gc_heap::last_gc_memory_load = 0;
-uint32_t gc_heap::high_memory_load_th;
+size_t gc_heap::last_gc_heap_size = 0;
-uint64_t gc_heap::total_physical_mem;
+size_t gc_heap::last_gc_fragmentation = 0;
-uint64_t gc_heap::entry_available_physical_mem;
+uint64_t gc_heap::mem_one_percent = 0;
+
+uint32_t gc_heap::high_memory_load_th = 0;
+
+uint64_t gc_heap::total_physical_mem = 0;
+
+uint64_t gc_heap::entry_available_physical_mem = 0;
#ifdef BACKGROUND_GC
GCEvent gc_heap::bgc_start_event;
@@ -5755,9 +5761,8 @@ void gc_mechanisms::init_mechanisms()
allocations_allowed = TRUE;
#endif //BACKGROUND_GC
-#ifdef BIT64
entry_memory_load = 0;
-#endif // BIT64
+ exit_memory_load = 0;
#ifdef STRESS_HEAP
stress_induced = FALSE;
@@ -19096,6 +19101,28 @@ size_t gc_heap::get_total_heap_size()
return total_heap_size;
}
+size_t gc_heap::get_total_fragmentation()
+{
+ size_t total_fragmentation = 0;
+
+#ifdef MULTIPLE_HEAPS
+ for (int i = 0; i < gc_heap::n_heaps; i++)
+ {
+ gc_heap* hp = gc_heap::g_heaps[i];
+#else //MULTIPLE_HEAPS
+ {
+ gc_heap* hp = pGenGCHeap;
+#endif //MULTIPLE_HEAPS
+ for (int i = 0; i <= (max_generation + 1); i++)
+ {
+ generation* gen = hp->generation_of (i);
+ total_fragmentation += (generation_free_list_space (gen) + generation_free_obj_space (gen));
+ }
+ }
+
+ return total_fragmentation;
+}
+
size_t gc_heap::committed_size()
{
generation* gen = generation_of (max_generation);
@@ -29663,8 +29690,11 @@ size_t gc_heap::desired_new_allocation (dynamic_data* dd,
}
else //large object heap
{
+ uint32_t memory_load = 0;
uint64_t available_physical = 0;
- get_memory_info (NULL, &available_physical);
+ get_memory_info (&memory_load, &available_physical);
+ if (heap_number == 0)
+ settings.exit_memory_load = memory_load;
if (available_physical > 1024*1024)
available_physical -= 1024*1024;
@@ -29899,6 +29929,7 @@ size_t gc_heap::joined_youngest_desired (size_t new_allocation)
{
uint32_t memory_load = 0;
get_memory_info (&memory_load);
+ settings.exit_memory_load = memory_load;
dprintf (2, ("Current emory load: %d", memory_load));
size_t final_total =
@@ -34882,6 +34913,14 @@ void gc_heap::do_post_gc()
settings.condemned_generation,
(settings.concurrent ? "BGC" : "GC")));
+ if (settings.exit_memory_load != 0)
+ last_gc_memory_load = settings.exit_memory_load;
+ else if (settings.entry_memory_load != 0)
+ last_gc_memory_load = settings.entry_memory_load;
+
+ last_gc_heap_size = get_total_heap_size();
+ last_gc_fragmentation = get_total_fragmentation();
+
GCHeap::UpdatePostGCCounters();
#ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
//if (g_fEnableARM)
@@ -35266,6 +35305,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;
+}
+
int GCHeap::GetGcLatencyMode()
{
return (int)(pGenGCHeap->settings.pause_mode);
diff --git a/src/gc/gcimpl.h b/src/gc/gcimpl.h
index 261e26e9aa..54aee1a2ed 100644
--- a/src/gc/gcimpl.h
+++ b/src/gc/gcimpl.h
@@ -168,6 +168,12 @@ public:
unsigned GetCondemnedGeneration();
+ void GetMemoryInfo(uint32_t* highMemLoadThreshold,
+ uint64_t* totalPhysicalMem,
+ uint32_t* lastRecordedMemLoad,
+ size_t* lastRecordedHeapSize,
+ size_t* lastRecordedFragmentation);
+
int GetGcLatencyMode();
int SetGcLatencyMode(int newLatencyMode);
diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h
index c7c6424d00..d532c8a13a 100644
--- a/src/gc/gcinterface.h
+++ b/src/gc/gcinterface.h
@@ -608,6 +608,20 @@ public:
===========================================================================
*/
+ // Gets memory related information -
+ // highMemLoadThreshold - physical memory load (in percentage) when GC will start to
+ // react aggressively to reclaim memory.
+ // totalPhysicalMem - the total amount of phyiscal memory available on the machine and the memory
+ // limit set on the container if running in a container.
+ // 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;
+
// Gets the current GC latency mode.
virtual int GetGcLatencyMode() = 0;
diff --git a/src/gc/gcpriv.h b/src/gc/gcpriv.h
index 2c66acef4a..90717420ce 100644
--- a/src/gc/gcpriv.h
+++ b/src/gc/gcpriv.h
@@ -489,7 +489,9 @@ public:
BOOL stress_induced;
#endif // STRESS_HEAP
+ // These are opportunistically set
uint32_t entry_memory_load;
+ uint32_t exit_memory_load;
void init_mechanisms(); //for each GC
void first_init(); // for the life of the EE
@@ -2479,6 +2481,8 @@ protected:
size_t get_total_heap_size ();
PER_HEAP_ISOLATED
size_t get_total_committed_size();
+ PER_HEAP_ISOLATED
+ size_t get_total_fragmentation();
PER_HEAP_ISOLATED
void get_memory_info (uint32_t* memory_load,
@@ -2969,6 +2973,15 @@ public:
#endif //BIT64
PER_HEAP_ISOLATED
+ uint32_t last_gc_memory_load;
+
+ PER_HEAP_ISOLATED
+ size_t last_gc_heap_size;
+
+ PER_HEAP_ISOLATED
+ size_t last_gc_fragmentation;
+
+ PER_HEAP_ISOLATED
uint32_t high_memory_load_th;
PER_HEAP_ISOLATED
diff --git a/src/mscorlib/src/System/GC.cs b/src/mscorlib/src/System/GC.cs
index 7119302e27..848141f006 100644
--- a/src/mscorlib/src/System/GC.cs
+++ b/src/mscorlib/src/System/GC.cs
@@ -66,6 +66,14 @@ namespace System
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern int SetGCLatencyMode(int newLatencyMode);
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void GetMemoryInfo(out uint highMemLoadThreshold,
+ out ulong totalPhysicalMem,
+ out uint lastRecordedMemLoad,
+ // The next two are size_t
+ out UIntPtr lastRecordedHeapSize,
+ out UIntPtr lastRecordedFragmentation);
+
[DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
internal static extern int _StartNoGCRegion(long totalSize, bool lohSizeKnown, long lohSize, bool disallowFullBlockingGC);
diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp
index 48efc11904..d564f9acd8 100644
--- a/src/vm/comutilnative.cpp
+++ b/src/vm/comutilnative.cpp
@@ -922,6 +922,18 @@ 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)
+{
+ FCALL_CONTRACT;
+
+ FC_GC_POLL_NOT_NEEDED();
+
+ return GCHeapUtilities::GetGCHeap()->GetMemoryInfo(highMemLoadThreshold, totalPhysicalMem,
+ lastRecordedMemLoad,
+ lastRecordedHeapSize, lastRecordedFragmentation);
+}
+FCIMPLEND
+
FCIMPL0(int, GCInterface::GetGcLatencyMode)
{
FCALL_CONTRACT;
diff --git a/src/vm/comutilnative.h b/src/vm/comutilnative.h
index 3e63a0479c..c604811c9e 100644
--- a/src/vm/comutilnative.h
+++ b/src/vm/comutilnative.h
@@ -111,6 +111,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 FCDECL0(int, GetGcLatencyMode);
static FCDECL1(int, SetGcLatencyMode, int newLatencyMode);
static FCDECL0(int, GetLOHCompactionMode);
diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h
index 92d75e3f90..998f62b908 100644
--- a/src/vm/ecalllist.h
+++ b/src/vm/ecalllist.h
@@ -840,6 +840,7 @@ FCFuncStart(gGCInterfaceFuncs)
FCFuncElement("_WaitForFullGCApproach", GCInterface::WaitForFullGCApproach)
FCFuncElement("_WaitForFullGCComplete", GCInterface::WaitForFullGCComplete)
FCFuncElement("_CollectionCount", GCInterface::CollectionCount)
+ FCFuncElement("GetMemoryInfo", GCInterface::GetMemoryInfo)
FCFuncElement("GetGCLatencyMode", GCInterface::GetGcLatencyMode)
FCFuncElement("SetGCLatencyMode", GCInterface::SetGcLatencyMode)
FCFuncElement("GetLOHCompactionMode", GCInterface::GetLOHCompactionMode)