Mercurial > hg > graal-jvmci-8
comparison src/share/vm/services/nmtDCmd.cpp @ 20360:833b0f92429a
8046598: Scalable Native memory tracking development
Summary: Enhance scalability of native memory tracking
Reviewed-by: coleenp, ctornqvi, gtriantafill
author | zgu |
---|---|
date | Wed, 27 Aug 2014 08:19:12 -0400 |
parents | 78bbf4d43a14 |
children |
comparison
equal
deleted
inserted
replaced
20359:4d3a43351904 | 20360:833b0f92429a |
---|---|
20 * or visit www.oracle.com if you need additional information or have any | 20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. | 21 * questions. |
22 * | 22 * |
23 */ | 23 */ |
24 #include "precompiled.hpp" | 24 #include "precompiled.hpp" |
25 | |
26 #include "runtime/mutexLocker.hpp" | |
25 #include "services/nmtDCmd.hpp" | 27 #include "services/nmtDCmd.hpp" |
26 #include "services/memReporter.hpp" | 28 #include "services/memReporter.hpp" |
27 #include "services/memTracker.hpp" | 29 #include "services/memTracker.hpp" |
28 #include "utilities/globalDefinitions.hpp" | 30 #include "utilities/globalDefinitions.hpp" |
29 | 31 |
47 "allocation activities at different callsites.", | 49 "allocation activities at different callsites.", |
48 "BOOLEAN", false, "false"), | 50 "BOOLEAN", false, "false"), |
49 _shutdown("shutdown", "request runtime to shutdown itself and free the " \ | 51 _shutdown("shutdown", "request runtime to shutdown itself and free the " \ |
50 "memory used by runtime.", | 52 "memory used by runtime.", |
51 "BOOLEAN", false, "false"), | 53 "BOOLEAN", false, "false"), |
52 _auto_shutdown("autoShutdown", "automatically shutdown itself under " \ | 54 _statistics("statistics", "print tracker statistics for tuning purpose.", \ |
53 "stress situation", | 55 "BOOLEAN", false, "false"), |
54 "BOOLEAN", true, "true"), | |
55 #ifndef PRODUCT | |
56 _debug("debug", "print tracker statistics. Debug only, not thread safe", \ | |
57 "BOOLEAN", false, "false"), | |
58 #endif | |
59 _scale("scale", "Memory usage in which scale, KB, MB or GB", | 56 _scale("scale", "Memory usage in which scale, KB, MB or GB", |
60 "STRING", false, "KB") { | 57 "STRING", false, "KB") { |
61 _dcmdparser.add_dcmd_option(&_summary); | 58 _dcmdparser.add_dcmd_option(&_summary); |
62 _dcmdparser.add_dcmd_option(&_detail); | 59 _dcmdparser.add_dcmd_option(&_detail); |
63 _dcmdparser.add_dcmd_option(&_baseline); | 60 _dcmdparser.add_dcmd_option(&_baseline); |
64 _dcmdparser.add_dcmd_option(&_summary_diff); | 61 _dcmdparser.add_dcmd_option(&_summary_diff); |
65 _dcmdparser.add_dcmd_option(&_detail_diff); | 62 _dcmdparser.add_dcmd_option(&_detail_diff); |
66 _dcmdparser.add_dcmd_option(&_shutdown); | 63 _dcmdparser.add_dcmd_option(&_shutdown); |
67 _dcmdparser.add_dcmd_option(&_auto_shutdown); | 64 _dcmdparser.add_dcmd_option(&_statistics); |
68 #ifndef PRODUCT | |
69 _dcmdparser.add_dcmd_option(&_debug); | |
70 #endif | |
71 _dcmdparser.add_dcmd_option(&_scale); | 65 _dcmdparser.add_dcmd_option(&_scale); |
72 } | 66 } |
73 | 67 |
68 | |
69 size_t NMTDCmd::get_scale(const char* scale) const { | |
70 if (scale == NULL) return 0; | |
71 return NMTUtil::scale_from_name(scale); | |
72 } | |
73 | |
74 void NMTDCmd::execute(DCmdSource source, TRAPS) { | 74 void NMTDCmd::execute(DCmdSource source, TRAPS) { |
75 // Check NMT state | |
76 // native memory tracking has to be on | |
77 if (MemTracker::tracking_level() == NMT_off) { | |
78 output()->print_cr("Native memory tracking is not enabled"); | |
79 return; | |
80 } else if (MemTracker::tracking_level() == NMT_minimal) { | |
81 output()->print_cr("Native memory tracking has been shutdown"); | |
82 return; | |
83 } | |
84 | |
75 const char* scale_value = _scale.value(); | 85 const char* scale_value = _scale.value(); |
76 size_t scale_unit; | 86 size_t scale_unit = get_scale(scale_value); |
77 if (strcmp(scale_value, "KB") == 0 || strcmp(scale_value, "kb") == 0) { | 87 if (scale_unit == 0) { |
78 scale_unit = K; | |
79 } else if (strcmp(scale_value, "MB") == 0 || | |
80 strcmp(scale_value, "mb") == 0) { | |
81 scale_unit = M; | |
82 } else if (strcmp(scale_value, "GB") == 0 || | |
83 strcmp(scale_value, "gb") == 0) { | |
84 scale_unit = G; | |
85 } else { | |
86 output()->print_cr("Incorrect scale value: %s", scale_value); | 88 output()->print_cr("Incorrect scale value: %s", scale_value); |
87 return; | 89 return; |
88 } | 90 } |
89 | 91 |
90 int nopt = 0; | 92 int nopt = 0; |
92 if (_detail.is_set() && _detail.value()) { ++nopt; } | 94 if (_detail.is_set() && _detail.value()) { ++nopt; } |
93 if (_baseline.is_set() && _baseline.value()) { ++nopt; } | 95 if (_baseline.is_set() && _baseline.value()) { ++nopt; } |
94 if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } | 96 if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; } |
95 if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } | 97 if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; } |
96 if (_shutdown.is_set() && _shutdown.value()) { ++nopt; } | 98 if (_shutdown.is_set() && _shutdown.value()) { ++nopt; } |
97 if (_auto_shutdown.is_set()) { ++nopt; } | 99 if (_statistics.is_set() && _statistics.value()) { ++nopt; } |
98 | |
99 #ifndef PRODUCT | |
100 if (_debug.is_set() && _debug.value()) { ++nopt; } | |
101 #endif | |
102 | 100 |
103 if (nopt > 1) { | 101 if (nopt > 1) { |
104 output()->print_cr("At most one of the following option can be specified: " \ | 102 output()->print_cr("At most one of the following option can be specified: " \ |
105 "summary, detail, baseline, summary.diff, detail.diff, shutdown" | 103 "summary, detail, baseline, summary.diff, detail.diff, shutdown"); |
106 #ifndef PRODUCT | |
107 ", debug" | |
108 #endif | |
109 ); | |
110 return; | 104 return; |
111 } else if (nopt == 0) { | 105 } else if (nopt == 0) { |
112 if (_summary.is_set()) { | 106 if (_summary.is_set()) { |
113 output()->print_cr("No command to execute"); | 107 output()->print_cr("No command to execute"); |
114 return; | 108 return; |
115 } else { | 109 } else { |
116 _summary.set_value(true); | 110 _summary.set_value(true); |
117 } | 111 } |
118 } | 112 } |
119 | 113 |
120 #ifndef PRODUCT | 114 // Serialize NMT query |
121 if (_debug.value()) { | 115 MutexLocker locker(MemTracker::query_lock()); |
122 output()->print_cr("debug command is NOT thread-safe, may cause crash"); | |
123 MemTracker::print_tracker_stats(output()); | |
124 return; | |
125 } | |
126 #endif | |
127 | |
128 // native memory tracking has to be on | |
129 if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) { | |
130 // if it is not on, what's the reason? | |
131 output()->print_cr("%s", MemTracker::reason()); | |
132 return; | |
133 } | |
134 | 116 |
135 if (_summary.value()) { | 117 if (_summary.value()) { |
136 BaselineTTYOutputer outputer(output()); | 118 report(true, scale_unit); |
137 MemTracker::print_memory_usage(outputer, scale_unit, true); | |
138 } else if (_detail.value()) { | 119 } else if (_detail.value()) { |
139 BaselineTTYOutputer outputer(output()); | 120 if (!check_detail_tracking_level(output())) { |
140 MemTracker::print_memory_usage(outputer, scale_unit, false); | 121 return; |
122 } | |
123 report(false, scale_unit); | |
141 } else if (_baseline.value()) { | 124 } else if (_baseline.value()) { |
142 if (MemTracker::baseline()) { | 125 MemBaseline& baseline = MemTracker::get_baseline(); |
143 output()->print_cr("Successfully baselined."); | 126 if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) { |
144 } else { | 127 output()->print_cr("Baseline failed"); |
145 output()->print_cr("Baseline failed."); | 128 } else { |
129 output()->print_cr("Baseline succeeded"); | |
146 } | 130 } |
147 } else if (_summary_diff.value()) { | 131 } else if (_summary_diff.value()) { |
148 if (MemTracker::has_baseline()) { | 132 MemBaseline& baseline = MemTracker::get_baseline(); |
149 BaselineTTYOutputer outputer(output()); | 133 if (baseline.baseline_type() >= MemBaseline::Summary_baselined) { |
150 MemTracker::compare_memory_usage(outputer, scale_unit, true); | 134 report_diff(true, scale_unit); |
151 } else { | 135 } else { |
152 output()->print_cr("No baseline to compare, run 'baseline' command first"); | 136 output()->print_cr("No baseline for comparison"); |
153 } | 137 } |
154 } else if (_detail_diff.value()) { | 138 } else if (_detail_diff.value()) { |
155 if (MemTracker::has_baseline()) { | 139 if (!check_detail_tracking_level(output())) { |
156 BaselineTTYOutputer outputer(output()); | 140 return; |
157 MemTracker::compare_memory_usage(outputer, scale_unit, false); | 141 } |
158 } else { | 142 MemBaseline& baseline = MemTracker::get_baseline(); |
159 output()->print_cr("No baseline to compare to, run 'baseline' command first"); | 143 if (baseline.baseline_type() == MemBaseline::Detail_baselined) { |
144 report_diff(false, scale_unit); | |
145 } else { | |
146 output()->print_cr("No detail baseline for comparison"); | |
160 } | 147 } |
161 } else if (_shutdown.value()) { | 148 } else if (_shutdown.value()) { |
162 MemTracker::shutdown(MemTracker::NMT_shutdown_user); | 149 MemTracker::shutdown(); |
163 output()->print_cr("Shutdown is in progress, it will take a few moments to " \ | 150 output()->print_cr("Native memory tracking has been turned off"); |
164 "completely shutdown"); | 151 } else if (_statistics.value()) { |
165 } else if (_auto_shutdown.is_set()) { | 152 if (check_detail_tracking_level(output())) { |
166 MemTracker::set_autoShutdown(_auto_shutdown.value()); | 153 MemTracker::tuning_statistics(output()); |
154 } | |
167 } else { | 155 } else { |
168 ShouldNotReachHere(); | 156 ShouldNotReachHere(); |
169 output()->print_cr("Unknown command"); | 157 output()->print_cr("Unknown command"); |
170 } | 158 } |
171 } | 159 } |
179 } else { | 167 } else { |
180 return 0; | 168 return 0; |
181 } | 169 } |
182 } | 170 } |
183 | 171 |
172 void NMTDCmd::report(bool summaryOnly, size_t scale_unit) { | |
173 MemBaseline baseline; | |
174 if (baseline.baseline(summaryOnly)) { | |
175 if (summaryOnly) { | |
176 MemSummaryReporter rpt(baseline, output(), scale_unit); | |
177 rpt.report(); | |
178 } else { | |
179 MemDetailReporter rpt(baseline, output(), scale_unit); | |
180 rpt.report(); | |
181 } | |
182 } | |
183 } | |
184 | |
185 void NMTDCmd::report_diff(bool summaryOnly, size_t scale_unit) { | |
186 MemBaseline& early_baseline = MemTracker::get_baseline(); | |
187 assert(early_baseline.baseline_type() != MemBaseline::Not_baselined, | |
188 "Not yet baselined"); | |
189 assert(summaryOnly || early_baseline.baseline_type() == MemBaseline::Detail_baselined, | |
190 "Not a detail baseline"); | |
191 | |
192 MemBaseline baseline; | |
193 if (baseline.baseline(summaryOnly)) { | |
194 if (summaryOnly) { | |
195 MemSummaryDiffReporter rpt(early_baseline, baseline, output(), scale_unit); | |
196 rpt.report_diff(); | |
197 } else { | |
198 MemDetailDiffReporter rpt(early_baseline, baseline, output(), scale_unit); | |
199 rpt.report_diff(); | |
200 } | |
201 } | |
202 } | |
203 | |
204 bool NMTDCmd::check_detail_tracking_level(outputStream* out) { | |
205 if (MemTracker::tracking_level() == NMT_detail) { | |
206 return true; | |
207 } else if (MemTracker::cmdline_tracking_level() == NMT_detail) { | |
208 out->print_cr("Tracking level has been downgraded due to lack of resources"); | |
209 return false; | |
210 } else { | |
211 out->print_cr("Detail tracking is not enabled"); | |
212 return false; | |
213 } | |
214 } |