changeset 10952:300be48156c5

8135200: Add White Box method that enumerates G1 old regions with less than specified liveness and collects statistics Reviewed-by: tschatzl, dfazunen, iignatyev
author kzhaldyb
date Wed, 20 Apr 2016 19:54:51 +0300
parents 7b35b32cd8d4
children 7e6a6560ceaf
files src/share/vm/prims/whitebox.cpp
diffstat 1 files changed, 64 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/prims/whitebox.cpp	Tue Apr 19 19:13:18 2016 +0300
+++ b/src/share/vm/prims/whitebox.cpp	Wed Apr 20 19:54:51 2016 +0300
@@ -38,6 +38,7 @@
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
+#include "memory/oopFactory.hpp"
 #include "oops/constantPool.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/wbtestmethods/parserTests.hpp"
@@ -374,6 +375,68 @@
   Handle h = MemoryService::create_MemoryUsage_obj(usage, CHECK_NULL);
   return JNIHandles::make_local(env, h());
 WB_END
+
+class OldRegionsLivenessClosure: public HeapRegionClosure {
+
+ private:
+  const int _liveness;
+  size_t _total_count;
+  size_t _total_memory;
+  size_t _total_memory_to_free;
+
+ public:
+  OldRegionsLivenessClosure(int liveness) :
+    _liveness(liveness),
+    _total_count(0),
+    _total_memory(0),
+    _total_memory_to_free(0) { }
+
+    size_t total_count() { return _total_count; }
+    size_t total_memory() { return _total_memory; }
+    size_t total_memory_to_free() { return _total_memory_to_free; }
+
+  bool doHeapRegion(HeapRegion* r) {
+    if (r->is_old()) {
+      size_t prev_live = r->marked_bytes();
+      size_t live = r->live_bytes();
+      size_t size = r->used();
+      size_t reg_size = HeapRegion::GrainBytes;
+      if (size > 0 && ((int)(live * 100 / size) < _liveness)) {
+        _total_memory += size;
+        ++_total_count;
+        if (size == reg_size) {
+        // we don't include non-full regions since they are unlikely included in mixed gc
+        // for testing purposes it's enough to have lowest estimation of total memory that is expected to be freed
+          _total_memory_to_free += size - prev_live;
+        }
+      }
+    }
+    return false;
+  }
+};
+
+
+WB_ENTRY(jlongArray, WB_G1GetMixedGCInfo(JNIEnv* env, jobject o, jint liveness))
+  if (!UseG1GC) {
+    THROW_MSG_NULL(vmSymbols::java_lang_RuntimeException(), "WB_G1GetMixedGCInfo: G1 is not enabled");
+  }
+  if (liveness < 0) {
+    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "liveness value should be non-negative");
+  }
+
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  OldRegionsLivenessClosure rli(liveness);
+  g1h->heap_region_iterate(&rli);
+
+  typeArrayOop result = oopFactory::new_longArray(3, CHECK_NULL);
+  result->long_at_put(0, rli.total_count());
+  result->long_at_put(1, rli.total_memory());
+  result->long_at_put(2, rli.total_memory_to_free());
+  return (jlongArray) JNIHandles::make_local(env, result);
+WB_END
+
+
+
 #endif // INCLUDE_ALL_GCS
 
 #if INCLUDE_NMT
@@ -1601,6 +1664,7 @@
                                                       (void*)&WB_G1AuxiliaryMemoryUsage  },
   {CC"psVirtualSpaceAlignment",CC"()J",               (void*)&WB_PSVirtualSpaceAlignment},
   {CC"psHeapGenerationAlignment",CC"()J",             (void*)&WB_PSHeapGenerationAlignment},
+  {CC"g1GetMixedGCInfo",   CC"(I)[J",                 (void*)&WB_G1GetMixedGCInfo },
 #endif // INCLUDE_ALL_GCS
 #if INCLUDE_NMT
   {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },