1.1 --- a/src/share/vm/services/nmtDCmd.cpp Wed Aug 27 09:36:55 2014 +0200 1.2 +++ b/src/share/vm/services/nmtDCmd.cpp Wed Aug 27 08:19:12 2014 -0400 1.3 @@ -22,6 +22,8 @@ 1.4 * 1.5 */ 1.6 #include "precompiled.hpp" 1.7 + 1.8 +#include "runtime/mutexLocker.hpp" 1.9 #include "services/nmtDCmd.hpp" 1.10 #include "services/memReporter.hpp" 1.11 #include "services/memTracker.hpp" 1.12 @@ -49,13 +51,8 @@ 1.13 _shutdown("shutdown", "request runtime to shutdown itself and free the " \ 1.14 "memory used by runtime.", 1.15 "BOOLEAN", false, "false"), 1.16 - _auto_shutdown("autoShutdown", "automatically shutdown itself under " \ 1.17 - "stress situation", 1.18 - "BOOLEAN", true, "true"), 1.19 -#ifndef PRODUCT 1.20 - _debug("debug", "print tracker statistics. Debug only, not thread safe", \ 1.21 + _statistics("statistics", "print tracker statistics for tuning purpose.", \ 1.22 "BOOLEAN", false, "false"), 1.23 -#endif 1.24 _scale("scale", "Memory usage in which scale, KB, MB or GB", 1.25 "STRING", false, "KB") { 1.26 _dcmdparser.add_dcmd_option(&_summary); 1.27 @@ -64,25 +61,30 @@ 1.28 _dcmdparser.add_dcmd_option(&_summary_diff); 1.29 _dcmdparser.add_dcmd_option(&_detail_diff); 1.30 _dcmdparser.add_dcmd_option(&_shutdown); 1.31 - _dcmdparser.add_dcmd_option(&_auto_shutdown); 1.32 -#ifndef PRODUCT 1.33 - _dcmdparser.add_dcmd_option(&_debug); 1.34 -#endif 1.35 + _dcmdparser.add_dcmd_option(&_statistics); 1.36 _dcmdparser.add_dcmd_option(&_scale); 1.37 } 1.38 1.39 + 1.40 +size_t NMTDCmd::get_scale(const char* scale) const { 1.41 + if (scale == NULL) return 0; 1.42 + return NMTUtil::scale_from_name(scale); 1.43 +} 1.44 + 1.45 void NMTDCmd::execute(DCmdSource source, TRAPS) { 1.46 + // Check NMT state 1.47 + // native memory tracking has to be on 1.48 + if (MemTracker::tracking_level() == NMT_off) { 1.49 + output()->print_cr("Native memory tracking is not enabled"); 1.50 + return; 1.51 + } else if (MemTracker::tracking_level() == NMT_minimal) { 1.52 + output()->print_cr("Native memory tracking has been shutdown"); 1.53 + return; 1.54 + } 1.55 + 1.56 const char* scale_value = _scale.value(); 1.57 - size_t scale_unit; 1.58 - if (strcmp(scale_value, "KB") == 0 || strcmp(scale_value, "kb") == 0) { 1.59 - scale_unit = K; 1.60 - } else if (strcmp(scale_value, "MB") == 0 || 1.61 - strcmp(scale_value, "mb") == 0) { 1.62 - scale_unit = M; 1.63 - } else if (strcmp(scale_value, "GB") == 0 || 1.64 - strcmp(scale_value, "gb") == 0) { 1.65 - scale_unit = G; 1.66 - } else { 1.67 + size_t scale_unit = get_scale(scale_value); 1.68 + if (scale_unit == 0) { 1.69 output()->print_cr("Incorrect scale value: %s", scale_value); 1.70 return; 1.71 } 1.72 @@ -94,19 +96,11 @@ 1.73 if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } 1.74 if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } 1.75 if (_shutdown.is_set() && _shutdown.value()) { ++nopt; } 1.76 - if (_auto_shutdown.is_set()) { ++nopt; } 1.77 - 1.78 -#ifndef PRODUCT 1.79 - if (_debug.is_set() && _debug.value()) { ++nopt; } 1.80 -#endif 1.81 + if (_statistics.is_set() && _statistics.value()) { ++nopt; } 1.82 1.83 if (nopt > 1) { 1.84 output()->print_cr("At most one of the following option can be specified: " \ 1.85 - "summary, detail, baseline, summary.diff, detail.diff, shutdown" 1.86 -#ifndef PRODUCT 1.87 - ", debug" 1.88 -#endif 1.89 - ); 1.90 + "summary, detail, baseline, summary.diff, detail.diff, shutdown"); 1.91 return; 1.92 } else if (nopt == 0) { 1.93 if (_summary.is_set()) { 1.94 @@ -117,53 +111,47 @@ 1.95 } 1.96 } 1.97 1.98 -#ifndef PRODUCT 1.99 - if (_debug.value()) { 1.100 - output()->print_cr("debug command is NOT thread-safe, may cause crash"); 1.101 - MemTracker::print_tracker_stats(output()); 1.102 + // Serialize NMT query 1.103 + MutexLocker locker(MemTracker::query_lock()); 1.104 + 1.105 + if (_summary.value()) { 1.106 + report(true, scale_unit); 1.107 + } else if (_detail.value()) { 1.108 + if (!check_detail_tracking_level(output())) { 1.109 return; 1.110 } 1.111 -#endif 1.112 - 1.113 - // native memory tracking has to be on 1.114 - if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { 1.115 - // if it is not on, what's the reason? 1.116 - output()->print_cr("%s", MemTracker::reason()); 1.117 + report(false, scale_unit); 1.118 + } else if (_baseline.value()) { 1.119 + MemBaseline& baseline = MemTracker::get_baseline(); 1.120 + if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) { 1.121 + output()->print_cr("Baseline failed"); 1.122 + } else { 1.123 + output()->print_cr("Baseline succeeded"); 1.124 + } 1.125 + } else if (_summary_diff.value()) { 1.126 + MemBaseline& baseline = MemTracker::get_baseline(); 1.127 + if (baseline.baseline_type() >= MemBaseline::Summary_baselined) { 1.128 + report_diff(true, scale_unit); 1.129 + } else { 1.130 + output()->print_cr("No baseline for comparison"); 1.131 + } 1.132 + } else if (_detail_diff.value()) { 1.133 + if (!check_detail_tracking_level(output())) { 1.134 return; 1.135 } 1.136 - 1.137 - if (_summary.value()) { 1.138 - BaselineTTYOutputer outputer(output()); 1.139 - MemTracker::print_memory_usage(outputer, scale_unit, true); 1.140 - } else if (_detail.value()) { 1.141 - BaselineTTYOutputer outputer(output()); 1.142 - MemTracker::print_memory_usage(outputer, scale_unit, false); 1.143 - } else if (_baseline.value()) { 1.144 - if (MemTracker::baseline()) { 1.145 - output()->print_cr("Successfully baselined."); 1.146 + MemBaseline& baseline = MemTracker::get_baseline(); 1.147 + if (baseline.baseline_type() == MemBaseline::Detail_baselined) { 1.148 + report_diff(false, scale_unit); 1.149 } else { 1.150 - output()->print_cr("Baseline failed."); 1.151 - } 1.152 - } else if (_summary_diff.value()) { 1.153 - if (MemTracker::has_baseline()) { 1.154 - BaselineTTYOutputer outputer(output()); 1.155 - MemTracker::compare_memory_usage(outputer, scale_unit, true); 1.156 - } else { 1.157 - output()->print_cr("No baseline to compare, run 'baseline' command first"); 1.158 - } 1.159 - } else if (_detail_diff.value()) { 1.160 - if (MemTracker::has_baseline()) { 1.161 - BaselineTTYOutputer outputer(output()); 1.162 - MemTracker::compare_memory_usage(outputer, scale_unit, false); 1.163 - } else { 1.164 - output()->print_cr("No baseline to compare to, run 'baseline' command first"); 1.165 + output()->print_cr("No detail baseline for comparison"); 1.166 } 1.167 } else if (_shutdown.value()) { 1.168 - MemTracker::shutdown(MemTracker::NMT_shutdown_user); 1.169 - output()->print_cr("Shutdown is in progress, it will take a few moments to " \ 1.170 - "completely shutdown"); 1.171 - } else if (_auto_shutdown.is_set()) { 1.172 - MemTracker::set_autoShutdown(_auto_shutdown.value()); 1.173 + MemTracker::shutdown(); 1.174 + output()->print_cr("Native memory tracking has been turned off"); 1.175 + } else if (_statistics.value()) { 1.176 + if (check_detail_tracking_level(output())) { 1.177 + MemTracker::tuning_statistics(output()); 1.178 + } 1.179 } else { 1.180 ShouldNotReachHere(); 1.181 output()->print_cr("Unknown command"); 1.182 @@ -181,3 +169,46 @@ 1.183 } 1.184 } 1.185 1.186 +void NMTDCmd::report(bool summaryOnly, size_t scale_unit) { 1.187 + MemBaseline baseline; 1.188 + if (baseline.baseline(summaryOnly)) { 1.189 + if (summaryOnly) { 1.190 + MemSummaryReporter rpt(baseline, output(), scale_unit); 1.191 + rpt.report(); 1.192 + } else { 1.193 + MemDetailReporter rpt(baseline, output(), scale_unit); 1.194 + rpt.report(); 1.195 + } 1.196 + } 1.197 +} 1.198 + 1.199 +void NMTDCmd::report_diff(bool summaryOnly, size_t scale_unit) { 1.200 + MemBaseline& early_baseline = MemTracker::get_baseline(); 1.201 + assert(early_baseline.baseline_type() != MemBaseline::Not_baselined, 1.202 + "Not yet baselined"); 1.203 + assert(summaryOnly || early_baseline.baseline_type() == MemBaseline::Detail_baselined, 1.204 + "Not a detail baseline"); 1.205 + 1.206 + MemBaseline baseline; 1.207 + if (baseline.baseline(summaryOnly)) { 1.208 + if (summaryOnly) { 1.209 + MemSummaryDiffReporter rpt(early_baseline, baseline, output(), scale_unit); 1.210 + rpt.report_diff(); 1.211 + } else { 1.212 + MemDetailDiffReporter rpt(early_baseline, baseline, output(), scale_unit); 1.213 + rpt.report_diff(); 1.214 + } 1.215 + } 1.216 +} 1.217 + 1.218 +bool NMTDCmd::check_detail_tracking_level(outputStream* out) { 1.219 + if (MemTracker::tracking_level() == NMT_detail) { 1.220 + return true; 1.221 + } else if (MemTracker::cmdline_tracking_level() == NMT_detail) { 1.222 + out->print_cr("Tracking level has been downgraded due to lack of resources"); 1.223 + return false; 1.224 + } else { 1.225 + out->print_cr("Detail tracking is not enabled"); 1.226 + return false; 1.227 + } 1.228 +}