Thu, 26 Sep 2013 12:49:45 +0200
8014078: G1: improve remembered set summary information by providing per region type information
Summary: Add memory consumption breakdown on a per region type in the G1 remembered set summary statistics. This simplifies remembered set memory consumption analysis.
Reviewed-by: brutisso
1.1 --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Sep 25 17:23:41 2013 +0200 1.2 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Sep 26 12:49:45 2013 +0200 1.3 @@ -3681,6 +3681,11 @@ 1.4 assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); 1.5 // Fill TLAB's and such 1.6 ensure_parsability(true); 1.7 + 1.8 + if (G1SummarizeRSetStats && (G1SummarizeRSetStatsPeriod > 0) && 1.9 + (total_collections() % G1SummarizeRSetStatsPeriod == 0)) { 1.10 + g1_rem_set()->print_periodic_summary_info("Before GC RS summary"); 1.11 + } 1.12 } 1.13 1.14 void G1CollectedHeap::gc_epilogue(bool full /* Ignored */) { 1.15 @@ -3689,7 +3694,7 @@ 1.16 (G1SummarizeRSetStatsPeriod > 0) && 1.17 // we are at the end of the GC. Total collections has already been increased. 1.18 ((total_collections() - 1) % G1SummarizeRSetStatsPeriod == 0)) { 1.19 - g1_rem_set()->print_periodic_summary_info(); 1.20 + g1_rem_set()->print_periodic_summary_info("After GC RS summary"); 1.21 } 1.22 1.23 // FIXME: what is this about?
2.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Sep 25 17:23:41 2013 +0200 2.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Sep 26 12:49:45 2013 +0200 2.3 @@ -731,12 +731,12 @@ 2.4 return has_refs_into_cset; 2.5 } 2.6 2.7 -void G1RemSet::print_periodic_summary_info() { 2.8 +void G1RemSet::print_periodic_summary_info(const char* header) { 2.9 G1RemSetSummary current; 2.10 current.initialize(this, n_workers()); 2.11 2.12 _prev_period_summary.subtract_from(¤t); 2.13 - print_summary_info(&_prev_period_summary); 2.14 + print_summary_info(&_prev_period_summary, header); 2.15 2.16 _prev_period_summary.set(¤t); 2.17 }
3.1 --- a/src/share/vm/gc_implementation/g1/g1RemSet.hpp Wed Sep 25 17:23:41 2013 +0200 3.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSet.hpp Thu Sep 26 12:49:45 2013 +0200 3.3 @@ -145,7 +145,7 @@ 3.4 virtual void print_summary_info(); 3.5 3.6 // Print accumulated summary info from the last time called. 3.7 - virtual void print_periodic_summary_info(); 3.8 + virtual void print_periodic_summary_info(const char* header); 3.9 3.10 // Prepare remembered set for verification. 3.11 virtual void prepare_for_verify();
4.1 --- a/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Wed Sep 25 17:23:41 2013 +0200 4.2 +++ b/src/share/vm/gc_implementation/g1/g1RemSetSummary.cpp Thu Sep 26 12:49:45 2013 +0200 4.3 @@ -125,25 +125,115 @@ 4.4 _sampling_thread_vtime = other->sampling_thread_vtime() - _sampling_thread_vtime; 4.5 } 4.6 4.7 +static double percent_of(size_t numerator, size_t denominator) { 4.8 + if (denominator != 0) { 4.9 + return (double)numerator / denominator * 100.0f; 4.10 + } else { 4.11 + return 0.0f; 4.12 + } 4.13 +} 4.14 + 4.15 +static size_t round_to_K(size_t value) { 4.16 + return value / K; 4.17 +} 4.18 + 4.19 +class RegionTypeCounter VALUE_OBJ_CLASS_SPEC { 4.20 +private: 4.21 + const char* _name; 4.22 + 4.23 + size_t _rs_mem_size; 4.24 + size_t _cards_occupied; 4.25 + size_t _amount; 4.26 + 4.27 + size_t _code_root_mem_size; 4.28 + size_t _code_root_elems; 4.29 + 4.30 + double rs_mem_size_percent_of(size_t total) { 4.31 + return percent_of(_rs_mem_size, total); 4.32 + } 4.33 + 4.34 + double cards_occupied_percent_of(size_t total) { 4.35 + return percent_of(_cards_occupied, total); 4.36 + } 4.37 + 4.38 + double code_root_mem_size_percent_of(size_t total) { 4.39 + return percent_of(_code_root_mem_size, total); 4.40 + } 4.41 + 4.42 + double code_root_elems_percent_of(size_t total) { 4.43 + return percent_of(_code_root_elems, total); 4.44 + } 4.45 + 4.46 + size_t amount() const { return _amount; } 4.47 + 4.48 +public: 4.49 + 4.50 + RegionTypeCounter(const char* name) : _name(name), _rs_mem_size(0), _cards_occupied(0), 4.51 + _amount(0), _code_root_mem_size(0), _code_root_elems(0) { } 4.52 + 4.53 + void add(size_t rs_mem_size, size_t cards_occupied, size_t code_root_mem_size, 4.54 + size_t code_root_elems) { 4.55 + _rs_mem_size += rs_mem_size; 4.56 + _cards_occupied += cards_occupied; 4.57 + _code_root_mem_size += code_root_mem_size; 4.58 + _code_root_elems += code_root_elems; 4.59 + _amount++; 4.60 + } 4.61 + 4.62 + size_t rs_mem_size() const { return _rs_mem_size; } 4.63 + size_t cards_occupied() const { return _cards_occupied; } 4.64 + 4.65 + size_t code_root_mem_size() const { return _code_root_mem_size; } 4.66 + size_t code_root_elems() const { return _code_root_elems; } 4.67 + 4.68 + void print_rs_mem_info_on(outputStream * out, size_t total) { 4.69 + out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(rs_mem_size()), rs_mem_size_percent_of(total), amount(), _name); 4.70 + } 4.71 + 4.72 + void print_cards_occupied_info_on(outputStream * out, size_t total) { 4.73 + out->print_cr(" %8d (%5.1f%%) entries by %zd %s regions", cards_occupied(), cards_occupied_percent_of(total), amount(), _name); 4.74 + } 4.75 + 4.76 + void print_code_root_mem_info_on(outputStream * out, size_t total) { 4.77 + out->print_cr(" %8dK (%5.1f%%) by %zd %s regions", round_to_K(code_root_mem_size()), code_root_mem_size_percent_of(total), amount(), _name); 4.78 + } 4.79 + 4.80 + void print_code_root_elems_info_on(outputStream * out, size_t total) { 4.81 + out->print_cr(" %8d (%5.1f%%) elements by %zd %s regions", code_root_elems(), code_root_elems_percent_of(total), amount(), _name); 4.82 + } 4.83 +}; 4.84 + 4.85 + 4.86 class HRRSStatsIter: public HeapRegionClosure { 4.87 - size_t _occupied; 4.88 +private: 4.89 + RegionTypeCounter _young; 4.90 + RegionTypeCounter _humonguous; 4.91 + RegionTypeCounter _free; 4.92 + RegionTypeCounter _old; 4.93 + RegionTypeCounter _all; 4.94 4.95 - size_t _total_rs_mem_sz; 4.96 size_t _max_rs_mem_sz; 4.97 HeapRegion* _max_rs_mem_sz_region; 4.98 4.99 - size_t _total_code_root_mem_sz; 4.100 + size_t total_rs_mem_sz() const { return _all.rs_mem_size(); } 4.101 + size_t total_cards_occupied() const { return _all.cards_occupied(); } 4.102 + 4.103 + size_t max_rs_mem_sz() const { return _max_rs_mem_sz; } 4.104 + HeapRegion* max_rs_mem_sz_region() const { return _max_rs_mem_sz_region; } 4.105 + 4.106 size_t _max_code_root_mem_sz; 4.107 HeapRegion* _max_code_root_mem_sz_region; 4.108 + 4.109 + size_t total_code_root_mem_sz() const { return _all.code_root_mem_size(); } 4.110 + size_t total_code_root_elems() const { return _all.code_root_elems(); } 4.111 + 4.112 + size_t max_code_root_mem_sz() const { return _max_code_root_mem_sz; } 4.113 + HeapRegion* max_code_root_mem_sz_region() const { return _max_code_root_mem_sz_region; } 4.114 + 4.115 public: 4.116 - HRRSStatsIter() : 4.117 - _occupied(0), 4.118 - _total_rs_mem_sz(0), 4.119 - _max_rs_mem_sz(0), 4.120 - _max_rs_mem_sz_region(NULL), 4.121 - _total_code_root_mem_sz(0), 4.122 - _max_code_root_mem_sz(0), 4.123 - _max_code_root_mem_sz_region(NULL) 4.124 + HRRSStatsIter() : _all("All"), _young("Young"), _humonguous("Humonguous"), 4.125 + _free("Free"), _old("Old"), _max_code_root_mem_sz_region(NULL), _max_rs_mem_sz_region(NULL), 4.126 + _max_rs_mem_sz(0), _max_code_root_mem_sz(0) 4.127 {} 4.128 4.129 bool doHeapRegion(HeapRegion* r) { 4.130 @@ -156,46 +246,95 @@ 4.131 _max_rs_mem_sz = rs_mem_sz; 4.132 _max_rs_mem_sz_region = r; 4.133 } 4.134 - _total_rs_mem_sz += rs_mem_sz; 4.135 - 4.136 + size_t occupied_cards = hrrs->occupied(); 4.137 size_t code_root_mem_sz = hrrs->strong_code_roots_mem_size(); 4.138 - if (code_root_mem_sz > _max_code_root_mem_sz) { 4.139 - _max_code_root_mem_sz = code_root_mem_sz; 4.140 + if (code_root_mem_sz > max_code_root_mem_sz()) { 4.141 _max_code_root_mem_sz_region = r; 4.142 } 4.143 - _total_code_root_mem_sz += code_root_mem_sz; 4.144 + size_t code_root_elems = hrrs->strong_code_roots_list_length(); 4.145 4.146 - size_t occ = hrrs->occupied(); 4.147 - _occupied += occ; 4.148 + RegionTypeCounter* current = NULL; 4.149 + if (r->is_young()) { 4.150 + current = &_young; 4.151 + } else if (r->isHumongous()) { 4.152 + current = &_humonguous; 4.153 + } else if (r->is_empty()) { 4.154 + current = &_free; 4.155 + } else { 4.156 + current = &_old; 4.157 + } 4.158 + current->add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); 4.159 + _all.add(rs_mem_sz, occupied_cards, code_root_mem_sz, code_root_elems); 4.160 + 4.161 return false; 4.162 } 4.163 - size_t total_rs_mem_sz() { return _total_rs_mem_sz; } 4.164 - size_t max_rs_mem_sz() { return _max_rs_mem_sz; } 4.165 - HeapRegion* max_rs_mem_sz_region() { return _max_rs_mem_sz_region; } 4.166 - size_t total_code_root_mem_sz() { return _total_code_root_mem_sz; } 4.167 - size_t max_code_root_mem_sz() { return _max_code_root_mem_sz; } 4.168 - HeapRegion* max_code_root_mem_sz_region() { return _max_code_root_mem_sz_region; } 4.169 - size_t occupied() { return _occupied; } 4.170 + 4.171 + void print_summary_on(outputStream* out) { 4.172 + RegionTypeCounter* counters[] = { &_young, &_humonguous, &_free, &_old, NULL }; 4.173 + 4.174 + out->print_cr("\n Current rem set statistics"); 4.175 + out->print_cr(" Total per region rem sets sizes = "SIZE_FORMAT"K." 4.176 + " Max = "SIZE_FORMAT"K.", 4.177 + round_to_K(total_rs_mem_sz()), round_to_K(max_rs_mem_sz())); 4.178 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 4.179 + (*current)->print_rs_mem_info_on(out, total_rs_mem_sz()); 4.180 + } 4.181 + 4.182 + out->print_cr(" Static structures = "SIZE_FORMAT"K," 4.183 + " free_lists = "SIZE_FORMAT"K.", 4.184 + round_to_K(HeapRegionRemSet::static_mem_size()), 4.185 + round_to_K(HeapRegionRemSet::fl_mem_size())); 4.186 + 4.187 + out->print_cr(" "SIZE_FORMAT" occupied cards represented.", 4.188 + total_cards_occupied()); 4.189 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 4.190 + (*current)->print_cards_occupied_info_on(out, total_cards_occupied()); 4.191 + } 4.192 + 4.193 + // Largest sized rem set region statistics 4.194 + HeapRegionRemSet* rem_set = max_rs_mem_sz_region()->rem_set(); 4.195 + out->print_cr(" Region with largest rem set = "HR_FORMAT", " 4.196 + "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.", 4.197 + HR_FORMAT_PARAMS(max_rs_mem_sz_region()), 4.198 + round_to_K(rem_set->mem_size()), 4.199 + round_to_K(rem_set->occupied())); 4.200 + 4.201 + // Strong code root statistics 4.202 + HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set(); 4.203 + out->print_cr(" Total heap region code root sets sizes = "SIZE_FORMAT"K." 4.204 + " Max = "SIZE_FORMAT"K.", 4.205 + round_to_K(total_code_root_mem_sz()), 4.206 + round_to_K(max_code_root_rem_set->strong_code_roots_mem_size())); 4.207 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 4.208 + (*current)->print_code_root_mem_info_on(out, total_code_root_mem_sz()); 4.209 + } 4.210 + 4.211 + out->print_cr(" "SIZE_FORMAT" code roots represented.", 4.212 + total_code_root_elems()); 4.213 + for (RegionTypeCounter** current = &counters[0]; *current != NULL; current++) { 4.214 + (*current)->print_code_root_elems_info_on(out, total_code_root_elems()); 4.215 + } 4.216 + 4.217 + out->print_cr(" Region with largest amount of code roots = "HR_FORMAT", " 4.218 + "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".", 4.219 + HR_FORMAT_PARAMS(max_code_root_mem_sz_region()), 4.220 + round_to_K(max_code_root_rem_set->strong_code_roots_mem_size()), 4.221 + round_to_K(max_code_root_rem_set->strong_code_roots_list_length())); 4.222 + } 4.223 }; 4.224 4.225 -double calc_percentage(size_t numerator, size_t denominator) { 4.226 - if (denominator != 0) { 4.227 - return (double)numerator / denominator * 100.0; 4.228 - } else { 4.229 - return 0.0f; 4.230 - } 4.231 -} 4.232 - 4.233 void G1RemSetSummary::print_on(outputStream* out) { 4.234 - out->print_cr("\n Concurrent RS processed "SIZE_FORMAT" cards", 4.235 + out->print_cr("\n Recent concurrent refinement statistics"); 4.236 + out->print_cr(" Processed "SIZE_FORMAT" cards", 4.237 num_concurrent_refined_cards()); 4.238 out->print_cr(" Of %d completed buffers:", num_processed_buf_total()); 4.239 out->print_cr(" %8d (%5.1f%%) by concurrent RS threads.", 4.240 num_processed_buf_total(), 4.241 - calc_percentage(num_processed_buf_rs_threads(), num_processed_buf_total())); 4.242 + percent_of(num_processed_buf_rs_threads(), num_processed_buf_total())); 4.243 out->print_cr(" %8d (%5.1f%%) by mutator threads.", 4.244 num_processed_buf_mutator(), 4.245 - calc_percentage(num_processed_buf_mutator(), num_processed_buf_total())); 4.246 + percent_of(num_processed_buf_mutator(), num_processed_buf_total())); 4.247 + out->print_cr(" Did %d coarsenings.", num_coarsenings()); 4.248 out->print_cr(" Concurrent RS threads times (s)"); 4.249 out->print(" "); 4.250 for (uint i = 0; i < _num_vtimes; i++) { 4.251 @@ -207,33 +346,5 @@ 4.252 4.253 HRRSStatsIter blk; 4.254 G1CollectedHeap::heap()->heap_region_iterate(&blk); 4.255 - // RemSet stats 4.256 - out->print_cr(" Total heap region rem set sizes = "SIZE_FORMAT"K." 4.257 - " Max = "SIZE_FORMAT"K.", 4.258 - blk.total_rs_mem_sz()/K, blk.max_rs_mem_sz()/K); 4.259 - out->print_cr(" Static structures = "SIZE_FORMAT"K," 4.260 - " free_lists = "SIZE_FORMAT"K.", 4.261 - HeapRegionRemSet::static_mem_size() / K, 4.262 - HeapRegionRemSet::fl_mem_size() / K); 4.263 - out->print_cr(" "SIZE_FORMAT" occupied cards represented.", 4.264 - blk.occupied()); 4.265 - HeapRegion* max_rs_mem_sz_region = blk.max_rs_mem_sz_region(); 4.266 - HeapRegionRemSet* max_rs_rem_set = max_rs_mem_sz_region->rem_set(); 4.267 - out->print_cr(" Max size region = "HR_FORMAT", " 4.268 - "size = "SIZE_FORMAT "K, occupied = "SIZE_FORMAT"K.", 4.269 - HR_FORMAT_PARAMS(max_rs_mem_sz_region), 4.270 - (max_rs_rem_set->mem_size() + K - 1)/K, 4.271 - (max_rs_rem_set->occupied() + K - 1)/K); 4.272 - out->print_cr(" Did %d coarsenings.", num_coarsenings()); 4.273 - // Strong code root stats 4.274 - out->print_cr(" Total heap region code-root set sizes = "SIZE_FORMAT"K." 4.275 - " Max = "SIZE_FORMAT"K.", 4.276 - blk.total_code_root_mem_sz()/K, blk.max_code_root_mem_sz()/K); 4.277 - HeapRegion* max_code_root_mem_sz_region = blk.max_code_root_mem_sz_region(); 4.278 - HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region->rem_set(); 4.279 - out->print_cr(" Max size region = "HR_FORMAT", " 4.280 - "size = "SIZE_FORMAT "K, num_elems = "SIZE_FORMAT".", 4.281 - HR_FORMAT_PARAMS(max_code_root_mem_sz_region), 4.282 - (max_code_root_rem_set->strong_code_roots_mem_size() + K - 1)/K, 4.283 - (max_code_root_rem_set->strong_code_roots_list_length())); 4.284 + blk.print_summary_on(out); 4.285 }
5.1 --- a/test/gc/g1/TestSummarizeRSetStats.java Wed Sep 25 17:23:41 2013 +0200 5.2 +++ b/test/gc/g1/TestSummarizeRSetStats.java Thu Sep 26 12:49:45 2013 +0200 5.3 @@ -25,140 +25,61 @@ 5.4 * @test TestSummarizeRSetStats.java 5.5 * @bug 8013895 5.6 * @library /testlibrary 5.7 - * @build TestSummarizeRSetStats 5.8 + * @build TestSummarizeRSetStatsTools TestSummarizeRSetStats 5.9 * @summary Verify output of -XX:+G1SummarizeRSetStats 5.10 * @run main TestSummarizeRSetStats 5.11 * 5.12 * Test the output of G1SummarizeRSetStats in conjunction with G1SummarizeRSetStatsPeriod. 5.13 */ 5.14 5.15 -import com.oracle.java.testlibrary.*; 5.16 -import java.lang.Thread; 5.17 -import java.util.ArrayList; 5.18 -import java.util.Arrays; 5.19 - 5.20 -class RunSystemGCs { 5.21 - // 4M size, both are directly allocated into the old gen 5.22 - static Object[] largeObject1 = new Object[1024 * 1024]; 5.23 - static Object[] largeObject2 = new Object[1024 * 1024]; 5.24 - 5.25 - static int[] temp; 5.26 - 5.27 - public static void main(String[] args) { 5.28 - // create some cross-references between these objects 5.29 - for (int i = 0; i < largeObject1.length; i++) { 5.30 - largeObject1[i] = largeObject2; 5.31 - } 5.32 - 5.33 - for (int i = 0; i < largeObject2.length; i++) { 5.34 - largeObject2[i] = largeObject1; 5.35 - } 5.36 - 5.37 - int numGCs = Integer.parseInt(args[0]); 5.38 - 5.39 - if (numGCs > 0) { 5.40 - // try to force a minor collection: the young gen is 4M, the 5.41 - // amount of data allocated below is roughly that (4*1024*1024 + 5.42 - // some header data) 5.43 - for (int i = 0; i < 1024 ; i++) { 5.44 - temp = new int[1024]; 5.45 - } 5.46 - } 5.47 - 5.48 - for (int i = 0; i < numGCs - 1; i++) { 5.49 - System.gc(); 5.50 - } 5.51 - } 5.52 -} 5.53 - 5.54 public class TestSummarizeRSetStats { 5.55 5.56 - public static String runTest(String[] additionalArgs, int numGCs) throws Exception { 5.57 - ArrayList<String> finalargs = new ArrayList<String>(); 5.58 - String[] defaultArgs = new String[] { 5.59 - "-XX:+UseG1GC", 5.60 - "-Xmn4m", 5.61 - "-Xmx20m", 5.62 - "-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking 5.63 - "-XX:+PrintGC", 5.64 - "-XX:+UnlockDiagnosticVMOptions", 5.65 - "-XX:G1HeapRegionSize=1M", 5.66 - }; 5.67 - 5.68 - finalargs.addAll(Arrays.asList(defaultArgs)); 5.69 - 5.70 - if (additionalArgs != null) { 5.71 - finalargs.addAll(Arrays.asList(additionalArgs)); 5.72 - } 5.73 - 5.74 - finalargs.add(RunSystemGCs.class.getName()); 5.75 - finalargs.add(String.valueOf(numGCs)); 5.76 - 5.77 - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 5.78 - finalargs.toArray(new String[0])); 5.79 - OutputAnalyzer output = new OutputAnalyzer(pb.start()); 5.80 - 5.81 - output.shouldHaveExitValue(0); 5.82 - 5.83 - String result = output.getStdout(); 5.84 - return result; 5.85 - } 5.86 - 5.87 - private static void expectStatistics(String result, int expectedCumulative, int expectedPeriodic) throws Exception { 5.88 - int actualTotal = result.split("Concurrent RS processed").length - 1; 5.89 - int actualCumulative = result.split("Cumulative RS summary").length - 1; 5.90 - 5.91 - if (expectedCumulative != actualCumulative) { 5.92 - throw new Exception("Incorrect amount of RSet summaries at the end. Expected " + expectedCumulative + ", got " + actualCumulative); 5.93 - } 5.94 - 5.95 - if (expectedPeriodic != (actualTotal - actualCumulative)) { 5.96 - throw new Exception("Incorrect amount of per-period RSet summaries at the end. Expected " + expectedPeriodic + ", got " + (actualTotal - actualCumulative)); 5.97 - } 5.98 - } 5.99 - 5.100 public static void main(String[] args) throws Exception { 5.101 String result; 5.102 5.103 - // no RSet statistics output 5.104 - result = runTest(null, 0); 5.105 - expectStatistics(result, 0, 0); 5.106 + if (!TestSummarizeRSetStatsTools.testingG1GC()) { 5.107 + return; 5.108 + } 5.109 5.110 - // no RSet statistics output 5.111 - result = runTest(null, 2); 5.112 - expectStatistics(result, 0, 0); 5.113 + // no remembered set summary output 5.114 + result = TestSummarizeRSetStatsTools.runTest(null, 0); 5.115 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0); 5.116 5.117 - // no RSet statistics output 5.118 - result = runTest(new String[] { "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 5.119 - expectStatistics(result, 0, 0); 5.120 + // no remembered set summary output 5.121 + result = TestSummarizeRSetStatsTools.runTest(null, 2); 5.122 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0); 5.123 5.124 - // single RSet statistics output at the end 5.125 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0); 5.126 - expectStatistics(result, 1, 0); 5.127 + // no remembered set summary output 5.128 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 5.129 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 0, 0); 5.130 5.131 - // single RSet statistics output at the end 5.132 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 2); 5.133 - expectStatistics(result, 1, 0); 5.134 + // single remembered set summary output at the end 5.135 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0); 5.136 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0); 5.137 5.138 - // single RSet statistics output 5.139 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 0); 5.140 - expectStatistics(result, 1, 0); 5.141 + // single remembered set summary output at the end 5.142 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 2); 5.143 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0); 5.144 5.145 - // two times RSet statistics output 5.146 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1); 5.147 - expectStatistics(result, 1, 1); 5.148 + // single remembered set summary output 5.149 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 0); 5.150 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 0); 5.151 5.152 - // four times RSet statistics output 5.153 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 5.154 - expectStatistics(result, 1, 3); 5.155 + // two times remembered set summary output 5.156 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1); 5.157 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2); 5.158 5.159 - // three times RSet statistics output 5.160 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=2" }, 3); 5.161 - expectStatistics(result, 1, 2); 5.162 + // four times remembered set summary output 5.163 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 3); 5.164 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 6); 5.165 5.166 - // single RSet statistics output 5.167 - result = runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=100" }, 3); 5.168 - expectStatistics(result, 1, 1); 5.169 + // three times remembered set summary output 5.170 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=2" }, 3); 5.171 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 4); 5.172 + 5.173 + // single remembered set summary output 5.174 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=100" }, 3); 5.175 + TestSummarizeRSetStatsTools.expectRSetSummaries(result, 1, 2); 5.176 } 5.177 } 5.178
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/gc/g1/TestSummarizeRSetStatsPerRegion.java Thu Sep 26 12:49:45 2013 +0200 6.3 @@ -0,0 +1,55 @@ 6.4 +/* 6.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. 6.11 + * 6.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.15 + * version 2 for more details (a copy is included in the LICENSE file that 6.16 + * accompanied this code). 6.17 + * 6.18 + * You should have received a copy of the GNU General Public License version 6.19 + * 2 along with this work; if not, write to the Free Software Foundation, 6.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.21 + * 6.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.23 + * or visit www.oracle.com if you need additional information or have any 6.24 + * questions. 6.25 + */ 6.26 + 6.27 +/* 6.28 + * @test TestSummarizeRSetStatsPerRegion.java 6.29 + * @bug 8014078 6.30 + * @library /testlibrary 6.31 + * @build TestSummarizeRSetStatsTools TestSummarizeRSetStatsPerRegion 6.32 + * @summary Verify output of -XX:+G1SummarizeRSetStats in regards to per-region type output 6.33 + * @run main TestSummarizeRSetStatsPerRegion 6.34 + */ 6.35 + 6.36 +import com.oracle.java.testlibrary.*; 6.37 +import java.lang.Thread; 6.38 +import java.util.ArrayList; 6.39 +import java.util.Arrays; 6.40 + 6.41 +public class TestSummarizeRSetStatsPerRegion { 6.42 + 6.43 + public static void main(String[] args) throws Exception { 6.44 + String result; 6.45 + 6.46 + if (!TestSummarizeRSetStatsTools.testingG1GC()) { 6.47 + return; 6.48 + } 6.49 + 6.50 + // single remembered set summary output at the end 6.51 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats" }, 0); 6.52 + TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 0); 6.53 + 6.54 + // two times remembered set summary output 6.55 + result = TestSummarizeRSetStatsTools.runTest(new String[] { "-XX:+G1SummarizeRSetStats", "-XX:G1SummarizeRSetStatsPeriod=1" }, 1); 6.56 + TestSummarizeRSetStatsTools.expectPerRegionRSetSummaries(result, 1, 2); 6.57 + } 6.58 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/test/gc/g1/TestSummarizeRSetStatsTools.java Thu Sep 26 12:49:45 2013 +0200 7.3 @@ -0,0 +1,154 @@ 7.4 +/* 7.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 7.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 7.7 + * 7.8 + * This code is free software; you can redistribute it and/or modify it 7.9 + * under the terms of the GNU General Public License version 2 only, as 7.10 + * published by the Free Software Foundation. 7.11 + * 7.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 7.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 7.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 7.15 + * version 2 for more details (a copy is included in the LICENSE file that 7.16 + * accompanied this code). 7.17 + * 7.18 + * You should have received a copy of the GNU General Public License version 7.19 + * 2 along with this work; if not, write to the Free Software Foundation, 7.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 7.21 + * 7.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 7.23 + * or visit www.oracle.com if you need additional information or have any 7.24 + * questions. 7.25 + */ 7.26 + 7.27 +/* 7.28 + * Common helpers for TestSummarizeRSetStats* tests 7.29 + */ 7.30 + 7.31 +import sun.management.ManagementFactoryHelper; 7.32 +import com.sun.management.HotSpotDiagnosticMXBean; 7.33 +import com.sun.management.VMOption; 7.34 + 7.35 +import com.oracle.java.testlibrary.*; 7.36 +import java.util.regex.Matcher; 7.37 +import java.util.regex.Pattern; 7.38 +import java.lang.Thread; 7.39 +import java.util.ArrayList; 7.40 +import java.util.Arrays; 7.41 + 7.42 +class VerifySummaryOutput { 7.43 + // 4M size, both are directly allocated into the old gen 7.44 + static Object[] largeObject1 = new Object[1024 * 1024]; 7.45 + static Object[] largeObject2 = new Object[1024 * 1024]; 7.46 + 7.47 + static int[] temp; 7.48 + 7.49 + public static void main(String[] args) { 7.50 + // create some cross-references between these objects 7.51 + for (int i = 0; i < largeObject1.length; i++) { 7.52 + largeObject1[i] = largeObject2; 7.53 + } 7.54 + 7.55 + for (int i = 0; i < largeObject2.length; i++) { 7.56 + largeObject2[i] = largeObject1; 7.57 + } 7.58 + 7.59 + int numGCs = Integer.parseInt(args[0]); 7.60 + 7.61 + if (numGCs > 0) { 7.62 + // try to force a minor collection: the young gen is 4M, the 7.63 + // amount of data allocated below is roughly that (4*1024*1024 + 7.64 + // some header data) 7.65 + for (int i = 0; i < 1024 ; i++) { 7.66 + temp = new int[1024]; 7.67 + } 7.68 + } 7.69 + 7.70 + for (int i = 0; i < numGCs - 1; i++) { 7.71 + System.gc(); 7.72 + } 7.73 + } 7.74 +} 7.75 + 7.76 +public class TestSummarizeRSetStatsTools { 7.77 + 7.78 + // the VM is currently run using G1GC, i.e. trying to test G1 functionality. 7.79 + public static boolean testingG1GC() { 7.80 + HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); 7.81 + 7.82 + VMOption option = diagnostic.getVMOption("UseG1GC"); 7.83 + if (option.getValue().equals("false")) { 7.84 + System.out.println("Skipping this test. It is only a G1 test."); 7.85 + return false; 7.86 + } 7.87 + return true; 7.88 + } 7.89 + 7.90 + public static String runTest(String[] additionalArgs, int numGCs) throws Exception { 7.91 + ArrayList<String> finalargs = new ArrayList<String>(); 7.92 + String[] defaultArgs = new String[] { 7.93 + "-XX:+UseG1GC", 7.94 + "-XX:+UseCompressedOops", 7.95 + "-Xmn4m", 7.96 + "-Xmx20m", 7.97 + "-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking 7.98 + "-XX:+PrintGC", 7.99 + "-XX:+UnlockDiagnosticVMOptions", 7.100 + "-XX:G1HeapRegionSize=1M", 7.101 + }; 7.102 + 7.103 + finalargs.addAll(Arrays.asList(defaultArgs)); 7.104 + 7.105 + if (additionalArgs != null) { 7.106 + finalargs.addAll(Arrays.asList(additionalArgs)); 7.107 + } 7.108 + 7.109 + finalargs.add(VerifySummaryOutput.class.getName()); 7.110 + finalargs.add(String.valueOf(numGCs)); 7.111 + 7.112 + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( 7.113 + finalargs.toArray(new String[0])); 7.114 + OutputAnalyzer output = new OutputAnalyzer(pb.start()); 7.115 + 7.116 + output.shouldHaveExitValue(0); 7.117 + 7.118 + String result = output.getStdout(); 7.119 + return result; 7.120 + } 7.121 + 7.122 + private static void checkCounts(int expected, int actual, String which) throws Exception { 7.123 + if (expected != actual) { 7.124 + throw new Exception("RSet summaries mention " + which + " regions an incorrect number of times. Expected " + expected + ", got " + actual); 7.125 + } 7.126 + } 7.127 + 7.128 + public static void expectPerRegionRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception { 7.129 + expectRSetSummaries(result, expectedCumulative, expectedPeriodic); 7.130 + int actualYoung = result.split("Young regions").length - 1; 7.131 + int actualHumonguous = result.split("Humonguous regions").length - 1; 7.132 + int actualFree = result.split("Free regions").length - 1; 7.133 + int actualOther = result.split("Old regions").length - 1; 7.134 + 7.135 + // the strings we check for above are printed four times per summary 7.136 + int expectedPerRegionTypeInfo = (expectedCumulative + expectedPeriodic) * 4; 7.137 + 7.138 + checkCounts(expectedPerRegionTypeInfo, actualYoung, "Young"); 7.139 + checkCounts(expectedPerRegionTypeInfo, actualHumonguous, "Humonguous"); 7.140 + checkCounts(expectedPerRegionTypeInfo, actualFree, "Free"); 7.141 + checkCounts(expectedPerRegionTypeInfo, actualOther, "Old"); 7.142 + } 7.143 + 7.144 + public static void expectRSetSummaries(String result, int expectedCumulative, int expectedPeriodic) throws Exception { 7.145 + int actualTotal = result.split("concurrent refinement").length - 1; 7.146 + int actualCumulative = result.split("Cumulative RS summary").length - 1; 7.147 + 7.148 + if (expectedCumulative != actualCumulative) { 7.149 + throw new Exception("Incorrect amount of RSet summaries at the end. Expected " + expectedCumulative + ", got " + actualCumulative); 7.150 + } 7.151 + 7.152 + if (expectedPeriodic != (actualTotal - actualCumulative)) { 7.153 + throw new Exception("Incorrect amount of per-period RSet summaries at the end. Expected " + expectedPeriodic + ", got " + (actualTotal - actualCumulative)); 7.154 + } 7.155 + } 7.156 +} 7.157 +