comparison src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @ 4095:bca17e38de00

6593758: RFE: Enhance GC ergonomics to dynamically choose ParallelGCThreads Summary: Select number of GC threads dynamically based on heap usage and number of Java threads Reviewed-by: johnc, ysr, jcoomes
author jmasa
date Tue, 09 Aug 2011 10:16:01 -0700
parents a88de71c4e3a
children 00dd86e542eb
comparison
equal deleted inserted replaced
4094:3a298e04d914 4095:bca17e38de00
1022 double* data) { 1022 double* data) {
1023 double min = data[0], max = data[0]; 1023 double min = data[0], max = data[0];
1024 double total = 0.0; 1024 double total = 0.0;
1025 LineBuffer buf(level); 1025 LineBuffer buf(level);
1026 buf.append("[%s (ms):", str); 1026 buf.append("[%s (ms):", str);
1027 for (uint i = 0; i < ParallelGCThreads; ++i) { 1027 for (uint i = 0; i < no_of_gc_threads(); ++i) {
1028 double val = data[i]; 1028 double val = data[i];
1029 if (val < min) 1029 if (val < min)
1030 min = val; 1030 min = val;
1031 if (val > max) 1031 if (val > max)
1032 max = val; 1032 max = val;
1033 total += val; 1033 total += val;
1034 buf.append(" %3.1lf", val); 1034 buf.append(" %3.1lf", val);
1035 } 1035 }
1036 buf.append_and_print_cr(""); 1036 buf.append_and_print_cr("");
1037 double avg = total / (double) ParallelGCThreads; 1037 double avg = total / (double) no_of_gc_threads();
1038 buf.append_and_print_cr(" Avg: %5.1lf, Min: %5.1lf, Max: %5.1lf, Diff: %5.1lf]", 1038 buf.append_and_print_cr(" Avg: %5.1lf, Min: %5.1lf, Max: %5.1lf, Diff: %5.1lf]",
1039 avg, min, max, max - min); 1039 avg, min, max, max - min);
1040 } 1040 }
1041 1041
1042 void G1CollectorPolicy::print_par_sizes(int level, 1042 void G1CollectorPolicy::print_par_sizes(int level,
1044 double* data) { 1044 double* data) {
1045 double min = data[0], max = data[0]; 1045 double min = data[0], max = data[0];
1046 double total = 0.0; 1046 double total = 0.0;
1047 LineBuffer buf(level); 1047 LineBuffer buf(level);
1048 buf.append("[%s :", str); 1048 buf.append("[%s :", str);
1049 for (uint i = 0; i < ParallelGCThreads; ++i) { 1049 for (uint i = 0; i < no_of_gc_threads(); ++i) {
1050 double val = data[i]; 1050 double val = data[i];
1051 if (val < min) 1051 if (val < min)
1052 min = val; 1052 min = val;
1053 if (val > max) 1053 if (val > max)
1054 max = val; 1054 max = val;
1055 total += val; 1055 total += val;
1056 buf.append(" %d", (int) val); 1056 buf.append(" %d", (int) val);
1057 } 1057 }
1058 buf.append_and_print_cr(""); 1058 buf.append_and_print_cr("");
1059 double avg = total / (double) ParallelGCThreads; 1059 double avg = total / (double) no_of_gc_threads();
1060 buf.append_and_print_cr(" Sum: %d, Avg: %d, Min: %d, Max: %d, Diff: %d]", 1060 buf.append_and_print_cr(" Sum: %d, Avg: %d, Min: %d, Max: %d, Diff: %d]",
1061 (int)total, (int)avg, (int)min, (int)max, (int)max - (int)min); 1061 (int)total, (int)avg, (int)min, (int)max, (int)max - (int)min);
1062 } 1062 }
1063 1063
1064 void G1CollectorPolicy::print_stats(int level, 1064 void G1CollectorPolicy::print_stats(int level,
1074 } 1074 }
1075 1075
1076 double G1CollectorPolicy::avg_value(double* data) { 1076 double G1CollectorPolicy::avg_value(double* data) {
1077 if (G1CollectedHeap::use_parallel_gc_threads()) { 1077 if (G1CollectedHeap::use_parallel_gc_threads()) {
1078 double ret = 0.0; 1078 double ret = 0.0;
1079 for (uint i = 0; i < ParallelGCThreads; ++i) { 1079 for (uint i = 0; i < no_of_gc_threads(); ++i) {
1080 ret += data[i]; 1080 ret += data[i];
1081 } 1081 }
1082 return ret / (double) ParallelGCThreads; 1082 return ret / (double) no_of_gc_threads();
1083 } else { 1083 } else {
1084 return data[0]; 1084 return data[0];
1085 } 1085 }
1086 } 1086 }
1087 1087
1088 double G1CollectorPolicy::max_value(double* data) { 1088 double G1CollectorPolicy::max_value(double* data) {
1089 if (G1CollectedHeap::use_parallel_gc_threads()) { 1089 if (G1CollectedHeap::use_parallel_gc_threads()) {
1090 double ret = data[0]; 1090 double ret = data[0];
1091 for (uint i = 1; i < ParallelGCThreads; ++i) { 1091 for (uint i = 1; i < no_of_gc_threads(); ++i) {
1092 if (data[i] > ret) { 1092 if (data[i] > ret) {
1093 ret = data[i]; 1093 ret = data[i];
1094 } 1094 }
1095 } 1095 }
1096 return ret; 1096 return ret;
1100 } 1100 }
1101 1101
1102 double G1CollectorPolicy::sum_of_values(double* data) { 1102 double G1CollectorPolicy::sum_of_values(double* data) {
1103 if (G1CollectedHeap::use_parallel_gc_threads()) { 1103 if (G1CollectedHeap::use_parallel_gc_threads()) {
1104 double sum = 0.0; 1104 double sum = 0.0;
1105 for (uint i = 0; i < ParallelGCThreads; i++) { 1105 for (uint i = 0; i < no_of_gc_threads(); i++) {
1106 sum += data[i]; 1106 sum += data[i];
1107 } 1107 }
1108 return sum; 1108 return sum;
1109 } else { 1109 } else {
1110 return data[0]; 1110 return data[0];
1113 1113
1114 double G1CollectorPolicy::max_sum(double* data1, double* data2) { 1114 double G1CollectorPolicy::max_sum(double* data1, double* data2) {
1115 double ret = data1[0] + data2[0]; 1115 double ret = data1[0] + data2[0];
1116 1116
1117 if (G1CollectedHeap::use_parallel_gc_threads()) { 1117 if (G1CollectedHeap::use_parallel_gc_threads()) {
1118 for (uint i = 1; i < ParallelGCThreads; ++i) { 1118 for (uint i = 1; i < no_of_gc_threads(); ++i) {
1119 double data = data1[i] + data2[i]; 1119 double data = data1[i] + data2[i];
1120 if (data > ret) { 1120 if (data > ret) {
1121 ret = data; 1121 ret = data;
1122 } 1122 }
1123 } 1123 }
1126 } 1126 }
1127 1127
1128 // Anything below that is considered to be zero 1128 // Anything below that is considered to be zero
1129 #define MIN_TIMER_GRANULARITY 0.0000001 1129 #define MIN_TIMER_GRANULARITY 0.0000001
1130 1130
1131 void G1CollectorPolicy::record_collection_pause_end() { 1131 void G1CollectorPolicy::record_collection_pause_end(int no_of_gc_threads) {
1132 double end_time_sec = os::elapsedTime(); 1132 double end_time_sec = os::elapsedTime();
1133 double elapsed_ms = _last_pause_time_ms; 1133 double elapsed_ms = _last_pause_time_ms;
1134 bool parallel = G1CollectedHeap::use_parallel_gc_threads(); 1134 bool parallel = G1CollectedHeap::use_parallel_gc_threads();
1135 assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(), 1135 assert(_cur_collection_pause_used_regions_at_start >= cset_region_length(),
1136 "otherwise, the subtraction below does not make sense"); 1136 "otherwise, the subtraction below does not make sense");
1138 _cur_collection_pause_used_regions_at_start - cset_region_length(); 1138 _cur_collection_pause_used_regions_at_start - cset_region_length();
1139 size_t cur_used_bytes = _g1->used(); 1139 size_t cur_used_bytes = _g1->used();
1140 assert(cur_used_bytes == _g1->recalculate_used(), "It should!"); 1140 assert(cur_used_bytes == _g1->recalculate_used(), "It should!");
1141 bool last_pause_included_initial_mark = false; 1141 bool last_pause_included_initial_mark = false;
1142 bool update_stats = !_g1->evacuation_failed(); 1142 bool update_stats = !_g1->evacuation_failed();
1143 set_no_of_gc_threads(no_of_gc_threads);
1143 1144
1144 #ifndef PRODUCT 1145 #ifndef PRODUCT
1145 if (G1YoungSurvRateVerbose) { 1146 if (G1YoungSurvRateVerbose) {
1146 gclog_or_tty->print_cr(""); 1147 gclog_or_tty->print_cr("");
1147 _short_lived_surv_rate_group->print(); 1148 _short_lived_surv_rate_group->print();
2302 2303
2303 void work(int i) { 2304 void work(int i) {
2304 ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size, i); 2305 ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size, i);
2305 // Back to zero for the claim value. 2306 // Back to zero for the claim value.
2306 _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, i, 2307 _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, i,
2308 _g1->workers()->active_workers(),
2307 HeapRegion::InitialClaimValue); 2309 HeapRegion::InitialClaimValue);
2308 jint regions_added = parKnownGarbageCl.marked_regions_added(); 2310 jint regions_added = parKnownGarbageCl.marked_regions_added();
2309 _hrSorted->incNumMarkedHeapRegions(regions_added); 2311 _hrSorted->incNumMarkedHeapRegions(regions_added);
2310 if (G1PrintParCleanupStats) { 2312 if (G1PrintParCleanupStats) {
2311 gclog_or_tty->print_cr(" Thread %d called %d times, added %d regions to list.", 2313 gclog_or_tty->print_cr(" Thread %d called %d times, added %d regions to list.",
2313 } 2315 }
2314 } 2316 }
2315 }; 2317 };
2316 2318
2317 void 2319 void
2318 G1CollectorPolicy::record_concurrent_mark_cleanup_end() { 2320 G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) {
2319 double start_sec; 2321 double start_sec;
2320 if (G1PrintParCleanupStats) { 2322 if (G1PrintParCleanupStats) {
2321 start_sec = os::elapsedTime(); 2323 start_sec = os::elapsedTime();
2322 } 2324 }
2323 2325
2329 (clear_marked_end_sec - start_sec) * 1000.0); 2331 (clear_marked_end_sec - start_sec) * 1000.0);
2330 } 2332 }
2331 2333
2332 if (G1CollectedHeap::use_parallel_gc_threads()) { 2334 if (G1CollectedHeap::use_parallel_gc_threads()) {
2333 const size_t OverpartitionFactor = 4; 2335 const size_t OverpartitionFactor = 4;
2334 const size_t MinWorkUnit = 8; 2336 size_t WorkUnit;
2335 const size_t WorkUnit = 2337 // The use of MinChunkSize = 8 in the original code
2336 MAX2(_g1->n_regions() / (ParallelGCThreads * OverpartitionFactor), 2338 // causes some assertion failures when the total number of
2337 MinWorkUnit); 2339 // region is less than 8. The code here tries to fix that.
2340 // Should the original code also be fixed?
2341 if (no_of_gc_threads > 0) {
2342 const size_t MinWorkUnit =
2343 MAX2(_g1->n_regions() / no_of_gc_threads, (size_t) 1U);
2344 WorkUnit =
2345 MAX2(_g1->n_regions() / (no_of_gc_threads * OverpartitionFactor),
2346 MinWorkUnit);
2347 } else {
2348 assert(no_of_gc_threads > 0,
2349 "The active gc workers should be greater than 0");
2350 // In a product build do something reasonable to avoid a crash.
2351 const size_t MinWorkUnit =
2352 MAX2(_g1->n_regions() / ParallelGCThreads, (size_t) 1U);
2353 WorkUnit =
2354 MAX2(_g1->n_regions() / (ParallelGCThreads * OverpartitionFactor),
2355 MinWorkUnit);
2356 }
2338 _collectionSetChooser->prepareForAddMarkedHeapRegionsPar(_g1->n_regions(), 2357 _collectionSetChooser->prepareForAddMarkedHeapRegionsPar(_g1->n_regions(),
2339 WorkUnit); 2358 WorkUnit);
2340 ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, 2359 ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser,
2341 (int) WorkUnit); 2360 (int) WorkUnit);
2342 _g1->workers()->run_task(&parKnownGarbageTask); 2361 _g1->workers()->run_task(&parKnownGarbageTask);