diff options
author | Ludovic Henry <luhenry@microsoft.com> | 2019-05-13 13:15:05 -0700 |
---|---|---|
committer | Vladimir Sadov <vsadov@microsoft.com> | 2019-05-13 13:15:04 -0700 |
commit | 934d73fea95b4c479b67fee0ff53caea4a325ee5 (patch) | |
tree | 35d0d77780d31625887625ef74f614327a9c3f00 /src/gc | |
parent | 24cdacaeb1e42a92051b32a6c4051b7a12ff2770 (diff) | |
download | coreclr-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.cpp | 36 | ||||
-rw-r--r-- | src/gc/gcimpl.h | 2 | ||||
-rw-r--r-- | src/gc/gcinterface.h | 2 | ||||
-rw-r--r-- | src/gc/gcpriv.h | 8 |
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; |