summaryrefslogtreecommitdiff
path: root/src/gc
diff options
context:
space:
mode:
authorLudovic Henry <luhenry@microsoft.com>2019-05-13 13:15:05 -0700
committerVladimir Sadov <vsadov@microsoft.com>2019-05-13 13:15:04 -0700
commit934d73fea95b4c479b67fee0ff53caea4a325ee5 (patch)
tree35d0d77780d31625887625ef74f614327a9c3f00 /src/gc
parent24cdacaeb1e42a92051b32a6c4051b7a12ff2770 (diff)
downloadcoreclr-934d73fea95b4c479b67fee0ff53caea4a325ee5.tar.gz
coreclr-934d73fea95b4c479b67fee0ff53caea4a325ee5.tar.bz2
coreclr-934d73fea95b4c479b67fee0ff53caea4a325ee5.zip
Implement GC.GetTotalAllocatedBytes (#23852)
* keep what's allocated so far on each heap * Implement GC.GetTotalAllocatedBytes It is based on https://github.com/dotnet/corefx/issues/34631 and https://github.com/dotnet/corefx/issues/30644 * Fixing races related to dead_threads_non_alloc_bytes * separated per-heap SOH and LOH counters. Different locks imply that we need different counters. * allow/ignore torn 64bit reads on 32bit in imprecise mode. * PR feedback * simplified the test a little to avoid OOM on ARM
Diffstat (limited to 'src/gc')
-rw-r--r--src/gc/gc.cpp36
-rw-r--r--src/gc/gcimpl.h2
-rw-r--r--src/gc/gcinterface.h2
-rw-r--r--src/gc/gcpriv.h8
4 files changed, 45 insertions, 3 deletions
diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp
index f240e73650..e8f2400c1b 100644
--- a/src/gc/gc.cpp
+++ b/src/gc/gc.cpp
@@ -2634,6 +2634,10 @@ gen_to_condemn_tuning gc_heap::gen_to_condemn_reasons;
size_t gc_heap::etw_allocation_running_amount[2];
+uint64_t gc_heap::total_alloc_bytes_soh = 0;
+
+uint64_t gc_heap::total_alloc_bytes_loh = 0;
+
int gc_heap::gc_policy = 0;
size_t gc_heap::allocation_running_time;
@@ -5950,6 +5954,8 @@ void gc_heap::fix_allocation_context (alloc_context* acontext, BOOL for_gc_p,
{
// We need to update the alloc_bytes to reflect the portion that we have not used
acontext->alloc_bytes -= (acontext->alloc_limit - acontext->alloc_ptr);
+ total_alloc_bytes_soh -= (acontext->alloc_limit - acontext->alloc_ptr);
+
acontext->alloc_ptr = 0;
acontext->alloc_limit = acontext->alloc_ptr;
}
@@ -10666,6 +10672,8 @@ gc_heap::init_gc_heap (int h_number)
etw_allocation_running_amount[0] = 0;
etw_allocation_running_amount[1] = 0;
+ total_alloc_bytes_soh = 0;
+ total_alloc_bytes_loh = 0;
//needs to be done after the dynamic data has been initialized
#ifndef MULTIPLE_HEAPS
@@ -11464,6 +11472,7 @@ void gc_heap::adjust_limit_clr (uint8_t* start, size_t limit_size, size_t size,
{
bool loh_p = (gen_number > 0);
GCSpinLock* msl = loh_p ? &more_space_lock_loh : &more_space_lock_soh;
+ uint64_t& total_alloc_bytes = loh_p ? total_alloc_bytes_loh : total_alloc_bytes_soh;
size_t aligned_min_obj_size = Align(min_obj_size, align_const);
@@ -11496,6 +11505,7 @@ void gc_heap::adjust_limit_clr (uint8_t* start, size_t limit_size, size_t size,
// when we are finishing an allocation from a free list
// we know that the free area was Align(min_obj_size) larger
acontext->alloc_bytes -= ac_size;
+ total_alloc_bytes -= ac_size;
size_t free_obj_size = ac_size + aligned_min_obj_size;
make_unused_array (hole, free_obj_size);
generation_free_obj_space (generation_of (gen_number)) += free_obj_size;
@@ -11514,7 +11524,9 @@ void gc_heap::adjust_limit_clr (uint8_t* start, size_t limit_size, size_t size,
}
}
acontext->alloc_limit = (start + limit_size - aligned_min_obj_size);
- acontext->alloc_bytes += limit_size - ((gen_number < max_generation + 1) ? aligned_min_obj_size : 0);
+ size_t added_bytes = limit_size - ((gen_number < max_generation + 1) ? aligned_min_obj_size : 0);
+ acontext->alloc_bytes += added_bytes;
+ total_alloc_bytes += added_bytes;
#ifdef FEATURE_APPDOMAIN_RESOURCE_MONITORING
if (g_fEnableAppDomainMonitoring)
@@ -11523,6 +11535,7 @@ void gc_heap::adjust_limit_clr (uint8_t* start, size_t limit_size, size_t size,
}
#endif //FEATURE_APPDOMAIN_RESOURCE_MONITORING
+
uint8_t* saved_used = 0;
if (seg)
@@ -12124,7 +12137,9 @@ void gc_heap::bgc_loh_alloc_clr (uint8_t* alloc_start,
}
}
#endif //VERIFY_HEAP
-
+
+ total_alloc_bytes_loh += size - Align (min_obj_size, align_const);
+
dprintf (SPINLOCK_LOG, ("[%d]Lmsl to clear large obj", heap_number));
add_saved_spinlock_info (true, me_release, mt_clr_large_mem);
leave_spin_lock (&more_space_lock_loh);
@@ -36039,6 +36054,23 @@ size_t GCHeap::GetTotalBytesInUse ()
#endif //MULTIPLE_HEAPS
}
+// Get the total allocated bytes
+uint64_t GCHeap::GetTotalAllocatedBytes()
+{
+#ifdef MULTIPLE_HEAPS
+ uint64_t total_alloc_bytes = 0;
+ for (int i = 0; i < gc_heap::n_heaps; i++)
+ {
+ gc_heap* hp = gc_heap::g_heaps[i];
+ total_alloc_bytes += hp->total_alloc_bytes_soh;
+ total_alloc_bytes += hp->total_alloc_bytes_loh;
+ }
+ return total_alloc_bytes;
+#else
+ return (pGenGCHeap->total_alloc_bytes_soh + pGenGCHeap->total_alloc_bytes_loh);
+#endif //MULTIPLE_HEAPS
+}
+
int GCHeap::CollectionCount (int generation, int get_bgc_fgc_count)
{
if (get_bgc_fgc_count != 0)
diff --git a/src/gc/gcimpl.h b/src/gc/gcimpl.h
index bdf3a5cc36..711ecb5fdc 100644
--- a/src/gc/gcimpl.h
+++ b/src/gc/gcimpl.h
@@ -76,6 +76,8 @@ public:
// Gets the amount of bytes objects currently occupy on the GC heap.
size_t GetCurrentObjSize();
+ uint64_t GetTotalAllocatedBytes();
+
size_t GetLastGCStartTime(int generation);
size_t GetLastGCDuration(int generation);
size_t GetNow();
diff --git a/src/gc/gcinterface.h b/src/gc/gcinterface.h
index c710d6d321..92e7987cbf 100644
--- a/src/gc/gcinterface.h
+++ b/src/gc/gcinterface.h
@@ -676,6 +676,8 @@ public:
// Gets the total number of bytes in use.
virtual size_t GetTotalBytesInUse() = 0;
+ virtual uint64_t GetTotalAllocatedBytes() = 0;
+
// Forces a garbage collection of the given generation. Also used extensively
// throughout the VM.
virtual HRESULT GarbageCollect(int generation = -1, bool low_memory_p = false, int mode = collection_blocking) = 0;
diff --git a/src/gc/gcpriv.h b/src/gc/gcpriv.h
index 2288ffee25..a4dd54f066 100644
--- a/src/gc/gcpriv.h
+++ b/src/gc/gcpriv.h
@@ -3006,12 +3006,18 @@ public:
size_t etw_allocation_running_amount[2];
PER_HEAP
+ uint64_t total_alloc_bytes_soh;
+
+ PER_HEAP
+ uint64_t total_alloc_bytes_loh;
+
+ PER_HEAP
int gc_policy; //sweep, compact, expand
#ifdef MULTIPLE_HEAPS
PER_HEAP_ISOLATED
bool gc_thread_no_affinitize_p;
-
+
PER_HEAP_ISOLATED
GCEvent gc_start_event;